Qt特性
Qt核心特点
Qt容器
Qt快捷键
Qt类库模块
Qt控件的使用
QSpinBox、QDoubleSpinBox
QTextEdit
进度条
时间控件
QPlainTextEdit
QComBox
QListWidget
QTreeWidget
QtableWidget
Model、View结构
QFileSystemModel
QStringListModel
QStandardItemModel
QItemSelectionModel
自定义代理-toc" style="margin-left:40px;">自定义代理
Qt对话框
QFileDialog
QColorDialog
QFontDialog
字符输入对话框
整形输入对话框
对话框输入浮点数
条目输入对话框
Question消息框
information消息框
warning消息框
critical消息框
about消息框
自定义对话框和调用
多窗体应用程序设计
SPlash和登录窗口
读写文本文件
QFile IODevice读写文件
QTextSteam读写文件
解决汉字乱码问题
读写二进制文件
使用QDataStream读写stm类型文件
使用QDataStream读写dat类型文件
使用DataStream读取.dat文件
文件目录操作
QPainter基本绘制
坐标系统和坐标转换
视觉坐标和窗口坐标
QtCharts
Qtchart绘制折线图
QBarChart
绘制饼状图(QPieChart)
绘制堆积图(QStackedBar)
绘制散点图(Scatterchart)
Qt特性
Qt核心特点
元对象编译器(Meta-Object Compiler,MOC)是一个预处理器 先将Qt的特性程序转换为标准C++程序,在由标准C++编译器进行编译
使用信号与槽机制,只有添加Q_OBJECT宏,moc才能对类里的信号与槽进行预处理
Qt为C++语言增加的特性在Qt Core模块里实现,由Qt的元对象系统实现。 包括:信号与槽机制、属性系统、动态类型转换等。
元对象系统(Meta-Object System)
QObject类是所有使用元对象系统的类的基类 在一个类的private部分声明Q_OBJECT宏 MOC(元对象编译器)为每个QObject的子类提供必要的代码
可以使用Qobject对象对Qt的控件进行控制
QObject *obj = new QMyWidget;
QWidget *widget = qobject_cast<QWidget *>(obj);
QMyWidget *myWidget = qobject_cast<QMyWidget *>(obj);
QLabel *label = qobject_cast<QLabel *>(obj); //不会报错,label为NULL
qobject_cast<QWidget *> 为类型转换,加了之前就相当于调用了指向QWidget的指针,可以对QWidget进行操作
qobject_cast<QLabel *>(obj);//obj原本指向QWidget,但使用QLabel对其进行指向,QWidget不包含QWidget的内容,因此返回的东西为Null;
Q_PROPERTY宏定义一个返回类型为type,名称为name的属性
class TestWidget : public QWidget { Q_OBJECT Q_CLASSINFO("author", "liu") };
TestWidget * test = new TestWidget; qDebug() << test->metaObject()->classInfo(0).name(); qDebug() << test->metaObject()->classInfo(0).value();
QClassInfo可以记录类的附加信息,通过metaobject进行调用获取
Qt容器
QMap是键值对关系 key不能重复 QMultiMap的key可以重复
QHash 和 QMap的区别 : QMap是连续存储的,里面的值也是按顺序存储的 QHash里面的值不一定是按顺序存储的,而是按映射存储的
QSet是基于散列表的
C++ Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值) 对于迭代器来说,可以修改实值,而不能修改key
C++vector容器的定义 vector<int>::iterator i; //定义正向迭代器
vector<int>::reverse_iterator j; //用反向迭代器遍历容器
Qt快捷键
F4 头文件和cpp进行切换 F2定义和实现之间进行切换 F1光标所在的符号显示帮助
Qt类库模块
其他模块都依赖于Qt Core模块,使用 qmake 构建,此模块会自动被加入项目 QT -= gui qmake 构建时,Qt GUI 模块是自动被加入项目的。如果项目中不使用 GUI 功能: QT += multimedia multimediawidgets QT += sql
Qt控件的使用
QSpinBox、QDoubleSpinBox
QSpinBox常用于现在整数prefix为前缀,sufix为后缀
QDoubleSpinBox常用于显示double,可以设置显示的小数点位数,前后缀方式与QSpinbox相同
QTextEdit
QTextEdit的palatte可以用来显示颜色,可做控制面板使用
QColor color; int R=ui->SliderRed->value(); //读取SliderRed的当前值 int G=ui->SliderGreen->value();//读取 SliderGreen 的当前值 int B=ui->SliderBlue->value();//读取 SliderBlue 的当前值 int alpha=ui->SliderAlpha->value();//读取 SliderAlpha 的当前值 color.setRgb(R,G,B,alpha); //使用QColor的setRgb()函数 获得颜色 QPalette pal=ui->textEdit->palette();//获取textEdit原有的 palette pal.setColor(QPalette::Base,color); //设置palette的基色(即背景色) ui->textEdit->setPalette(pal);//设置为textEdit的palette,改变textEdit的底色
进度条
QSlider为滑动条,值改变的槽函数为valuechanged(int)
QScollBar也为滑动条,类似网页下面的滑动条,值改变的槽函数为valuechanged(int)
QProgressBa为进度条,可以显示百分比及进度,类似软件界面启动加载界面,值改变的槽函数为valuechanged(int),但不可滑动类型QSlider和QScollBar改变他的值
QDial类似一个钟表,滑动可以改变他的值,值改变的槽函数为valuechanged(int)
QLCDNumber
QLCDNumber常用于显示数字和时间等,可以进行二进制、八进制、十进制、十六进制转换显示,也可以设置显示的位数,通过display设置显示的内容
ui->LCDDisaplay为ui界面的QLCDNumber控件
ui->LCDDisplay->display(value);
//设置LCD显示二进制数 ui->LCDDisplay->setDigitCount(8); ui->LCDDisplay->setBinMode();
//设置LCD显示八进制数 ui->LCDDisplay->setDigitCount(4); ui->LCDDisplay->setOctMode();
//设置LCD显示十六进制数 ui->LCDDisplay->setDigitCount(3); ui->LCDDisplay->setHexMode();
//设置LCD显示十进制数 ui->LCDDisplay->setDigitCount(3); ui->LCDDisplay->setDecMode();
时间控件
QTimeEdit用于显示当前时间的时分秒
QDateTime curDateTime=QDateTime::currentDateTime(); //读取当前日期时间 //editTime为QlineEdit控件,使用字符转换显示时间 ui->timeEdit->setTime(curDateTime.time()); //设置时间 ui->editTime->setText(curDateTime.toString("hh:mm:ss"));//转换为字符串显示
QDateEdit用于显示年月日
//editDate为QlineEdit控件,使用字符转换显示时间 ui->dateEdit->setDate(curDateTime.date());//设置日期 ui->editDate->setText(curDateTime.toString("yyyy-MM-dd"));//转换为字符串显示
QDateTimeedit用于显示完整的时间年月日时分秒
//editDateTime为QlineEdit控件,使用字符转换显示时间 ui->dateTimeEdit->setDateTime(curDateTime);//设置日期时间 ui->editDateTime->setText(curDateTime.toString("yyyy-MM-dd hh:mm:ss"));//转换为字符串显示
QCalendarWidget为日历控件,用于显示日历,槽函数为selectionChanged()函数,使用QDate可以获取日历上选择的时间
void Dialog::on_calendarWidget_selectionChanged() { //在日历上选择日期 QDate dt=ui->calendarWidget->selectedDate(); //读取选择的日期时间 QString str=dt.toString("yyyy年M月d日");//转换为字符串 ui->editCalendar->setText(str); //字符串显示日期 }
QPlainTextEdit
可以通过设置Qt界面的Property中的lineWrapMode属性来设置是否自动换行,NoWrap为不自动换行
appendPlainText()为在QPlainTextEdit后面添加内容
QPlainTextEdit的文字内容以QTextDocument类型储存,函数document返回这个文档对象的指针。 QTextDocument是内存中的文本对象,以文本块的方式储存,每个段落以换行符结束 QTextDocument提供一些函数实现对文本内容的存取 int blockCount(),返回文本块个数 QTextBlock finBlockByNumber(int ),读取一个文本块,序号从0开始
QTextDocument * doc = ui->plainTextEdit->document(); int count = doc->blockCount(); QIcon ico(":/imasges/icons/aim.ico"); for (int i = 0; i < count ; i++) { ui->comboBox->addItem(ico, doc->findBlockByNumber(i).text()); }
QComBox
QIcon ico(":/imasges/icons/UNIT.ICO"); QMap<QString, int> City_Zone; City_Zone.insert("北京",10); City_Zone.insert("上海",21); City_Zone.insert("天津",22); City_Zone.insert("大连",411); City_Zone.insert("锦州",416); City_Zone.insert("徐州",516); City_Zone.insert("福州",591); City_Zone.insert("青岛",532); foreach(auto str, City_Zone.keys()) { ui->comboBox2->addItem(ico, str, City_Zone.value(str)); } 通过foreach设置Qcombox的icon和值,addItem的第一个参数为icon,第二个参数为显示的内容,第三个参数为value
槽事件 currentIndexChanged(const QSting & arg1); if(!arg1.isEmpty()) { //获取的是QComBox的第三个设置的值 QString zone = ui->comboBox2->currentData().toString(); ui->plainTextEdit->appendPlainText(arg1 + "区号" + zone); } 槽事件中返回的参数为additem的第二个参数,currentData()为addItem中设置的第三个参数
QListWidget
通过QListWidgetItem来获取QListWidget上的表项
QListWidgetItem * aItem = ui->listWidget->item(i);
//通过setFlags来设置QListWidget上的表项的可用、可编辑、可选择等 aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable| Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);
QListWidgetItem可在前面添加Icon
QListWidgetItem * aItem; QIcon icon(":/images/icons/check2.ico"); QString str = QString::asprintf("New Insert append"); aItem = new QListWidgetItem(str); aItem->setIcon(icon); aItem->setCheckState(Qt::Checked); ui->listWidget->addItem(aItem);
QActon可添加QMenu
QMenu * menu = new QMenu(this); menu->addAction(ui->actSelALL); menu->addAction(ui->actSelNone); menu->addAction(ui->actSelInvs); ui->actSelPopMenu->setMenu(menu);
QDockWidegt
QDockWidegt设置可见性和浮动性
void MainWindow::on_actDockVisible_triggered(bool arg1) { ui->dockWidget->setVisible(arg1); } void MainWindow::on_actDockFloat_triggered(bool checked) { ui->dockWidget->setFloating(checked); }
QDockWidegt自身具体槽事件,来监听QDockWidegtd的可见性状态和浮动性状态topLevelChanged(bool topLevel)和visibilityChanged(bool visible)
void MainWindow::on_dockWidget_topLevelChanged(bool topLevel) { ui->actDockFloat->setChecked(topLevel); } void MainWindow::on_dockWidget_visibilityChanged(bool visible) { ui->actDockVisible->setChecked(visible); }
QTreeWidget
QTreeWidget通过QTreeWidgetItem来获取QTreeWidget的某项数据,QTreeWidgetItem的数据分为两部分
可以通过枚举类型对QTreeWidget节点类型进行区分
//枚举类型treeItemType, 用于创建 QTreeWidgetItem 时作为节点的type, 自定义类型必须大于1000 //itTopItem 顶层节点; itGroupItem 组节点; itImageItem 图片 enum treeItemType{itTopItem=1001,itGroupItem,itImageItem}; //枚举类型,表示列号 enum treeColNum{colItem=0, colItemType=1}; //目录树列的编号定义
QTreeWidgetItem * parItem = ui->treeWidget->currentItem(); QTreeWidgetItem * item = new QTreeWidgetItem(itGroupItem); QIcon icon(":/images/icons/open3.bmp"); item->setIcon(colItem, icon); item->setText(colItem, dir); item->setText(colItemType, "type:group"); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate); //设置节点选项 item->setCheckState(colItem,Qt::Checked); //节点选中 //通过setData向QTreeWidgetItem里面设置数据 item->setData(colItem,Qt::UserRole,QVariant(fullname)); //设置角色为Qt::UserRole的Data,存储完整目录名称 parItem->addChild(item); //在父节点下面添加子节点
//QTreeWidget的表项改变事件 void MainWindow::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous); if(current==NULL) return; //获取之前设置的枚举类型 int var = current->type(); switch (var) { case itTopItem: ui->actAddFiles->setEnabled(true); ui->actAddFolder->setEnabled(true); ui->actDeleteItem->setEnabled(true); break; case itGroupItem: ui->actAddFiles->setEnabled(true); ui->actAddFolder->setEnabled(true); ui->actDeleteItem->setEnabled(true); break; case itImageItem: ui->actAddFiles->setEnabled(true); ui->actAddFolder->setEnabled(false); ui->actDeleteItem->setEnabled(true); ui->actZoomIn->setEnabled(true); ui->actZoomFitH->setEnabled(true); ui->actZoomFitW->setEnabled(true); ui->actZoomOut->setEnabled(true); ui->actZoomRealSize->setEnabled(true); LabFileName.setText(current->data(colItem,Qt::UserRole).toString()); //获取QTreeWidgetItem之前设置的数据 curPixmap.load(current->data(colItem,Qt::UserRole).toString()); on_actZoomFitW_triggered(); } }
QtableWidget
通过ui界面设置tabsCloseable设置QtableWidget是否具有关闭按钮。
//将ui的center设置为Qtablewidget setCentralWidget(ui->tabWidget); //设置是否可见 ui->tabWidget->setVisible(false); //设置全屏显示 //setWindowState(Qt::WindowMaximized);
Model、View结构
•数据:如数据库的一个数据表或SQL查询结果,内存中的一个 StringList,或磁盘文件结构等。
•Model:与数据通信,并为视图组件提供数据接口。
•View:是屏幕上的界面组件,视图从数据模型获得每个数据项的模型索引(model index),通过模型索引获取数据
•代理:定制数据的界面显示和编辑方式。在标准的视图组件中,代理功能显示一个数据,当数据被编辑时,提供一个编辑器,一般是QLineEdit 。
模型、视图和代理之间使用信号和槽通信
数据类型
QStringListModel | 用于处理字符串列表数据的数据模型类 |
QStandardltemModel | 标准的基于项数据的数据模型类,每个项数据可以是任何数据类型 |
QFileSystemModel | 计算机上文件系统的数据模型类 |
QSortFilterProxyModel | 与其他数据模型结合,提供排序和过滤功能的数据模型类 |
QSqlQueryModel | 用于数据库SQL查询结果的数据模型类 |
QSqlTableModel | 用于数据库的一个数据表的数据模型类 |
QSqlRelationalTableModel | 用于关系型数据表的数据模型类 |
数据模型中存储数据的基本单元都是项(item),每个项有一个行号、一个列号,还有一个父项
QModelIndex 表示模型索引的类。模型索引提供数据存取的一个临时指针
//Table Model QModelIndex indexA = model->index(0, 0, QModelIndex()); QModelIndex indexC = model->index(2, 1, QModelIndex()); //Tree Model indexA 表示indexB的根节点 QModelIndex indexB = model->index(1, 0, indexA);
QFileSystemModel
如同 Widnows 的资源管理器一样。使用 QFileSystemModel 提供的接口函数,可以创建目录、删除目录、重命名目录,可以获得文件名称、目录名称、文件大小等参数,还可以获得文件的详细信息。
QFileSystemModel * model = new QFileSystemModel; model->setRootPath(QDir::currentPath());
//通过QFileSystemModel,使用QTreeView、QListView、QTableView可以直接通过QModleIndex调用QFileSystemModel读取的内容
//给出this指针,当窗体关闭的时候,指针会自动进行回收 //直接给TreeView ListView tableView设置文件模型,即可显示文件基本信息(类似文件管理器) fileMode = new QFileSystemModel(this); fileMode->setRootPath(QDir::currentPath()); ui->treeView->setModel(fileMode); ui->listView->setModel(fileMode); ui->tableView->setModel(fileMode); ui->tableView->verticalHeader()->setVisible(false); //连接信号,当QTreeViewd的表项发生变化时,QListView、QTableView发生相应的变化 connect(ui->treeView, SIGNAL(clicked(QModelIndex)), ui->listView, SLOT(setRootIndex(QModelIndex))); connect(ui->treeView, SIGNAL(clicked(QModelIndex)), ui->tableView, SLOT(setRootIndex(QModelIndex)));
可以通过QModelIndex来获取QFileSystemModel存取的信息
void MainWindow::on_treeView_clicked(const QModelIndex &index) { //通过QFileSystemModel的QModelIndex来获取文件名、文件大小、文件类型、及是否是文件夹 ui->labName->setText(fileMode->fileName(index)); ui->labPath->setText(fileMode->filePath(index)); ui->labType->setText(fileMode->type(index)); unsigned sz = fileMode->size(index) / 1024; if(sz < 1024) { ui->labSize->setText(QString::asprintf("%d kb", sz)); } else { ui->labSize->setText(QString::asprintf("%2F kb", (float)sz/1024)); } ui->checkBox->setChecked(fileMode->isDir(index)); }
QStringListModel
//定义QStringListModel QStringListModel *themodel;
//设置QStringListModel 的数据
theModle = new QStringListModel(this); QStringList theStrList; //保存初始 StringList theStrList<<"北京"<<"上海"<<"天津"<<"河北"<<"山东"<<"四川"<<"重庆"<<"广东"<<"河南"; //初始化 StringList theModle->setStringList(theStrList); //给QListView设置模式,即将QStringListModel的值给给QListView设置模式 ui->listView_2->setModel(theModle);
//获取QStringListModel设置的值 QStringList strlist = theModle->stringList(); //将从QStringListModel获取的值设置到QPlainTextEdit中去 foreach(auto str, strlist) { ui->plainTextEdit_2->appendPlainText(str); }
QStandardItemModel
#define FixedColumnCount 6 QStandardItemModel *theModel;//数据模型 QItemSelectionModel *theSelection;//Item选择模型 //为tableView设置数据模型 打通了Mode和View之间的关系 theModel = new QStandardItemModel(10, FixedColumnCount, this); theSelection = new QItemSelectionModel(theModel); ui->tableView->setModel(theModel); //设置数据模型 ui->tableView->setSelectionModel(theSelection);//设置选择模型
QStandardItemModel添加数据
void MainWindow::iniModelFromStringList(QStringList& aFileContent) { //从一个StringList 获取数据,初始化数据Model int rowCnt=aFileContent.count(); //文本行数,第1行是标题 theModel->setRowCount(rowCnt-1); //实际数据行数 //设置表头 QString header=aFileContent.at(0);//第1行是表头 //一个或多个空格、TAB等分隔符隔开的字符串, 分解为一个StringList QStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts); theModel->setHorizontalHeaderLabels(headerList); //设置表头文字 //设置表格数据 int j; QStandardItem *aItem; for (int i=1;i<rowCnt;i++) { QString aLineText=aFileContent.at(i); //获取 数据区 的一行 //一个或多个空格、TAB等分隔符隔开的字符串, 分解为一个StringList QStringList tmpList=aLineText.split(QRegExp("\\s+"),QString::SkipEmptyParts); for (j=0;j<FixedColumnCount-1;j++) //tmpList的行数等于FixedColumnCount, 固定的 { //不包含最后一列 aItem=new QStandardItem(tmpList.at(j));//创建item theModel->setItem(i-1,j,aItem); //为模型的某个行列位置设置Item } aItem=new QStandardItem(headerList.at(j));//最后一列是Checkable,需要设置 aItem->setCheckable(true); //设置为Checkable if (tmpList.at(j)=="0") aItem->setCheckState(Qt::Unchecked); //根据数据设置check状态 else aItem->setCheckState(Qt::Checked); theModel->setItem(i-1,j,aItem); //为模型的某个行列位置设置Item } }
//设置QStandardItemModel表头 QStringList headerList; headerList<<"Depth"<<"Measured Depth"<<"Direction"<<"Offset"<<"Quality"<<"Sampled"; theModel->setHorizontalHeaderLabels(headerList); //设置表头文字 //设置QStandardItemModel行数 theModel->setColumnCount(5);
使用文件输入输出流读写文件
//打开文件 QString curPath=QCoreApplication::applicationDirPath(); //获取应用程序的路径 //调用打开文件对话框打开一个文件 QString aFileName=QFileDialog::getOpenFileName(this,"打开一个文件",curPath, "井数据文件(*.txt);;所有文件(*.*)"); if (aFileName.isEmpty()) return; //如果未选择文件,退出 QStringList fFileContent;//文件内容字符串列表 QFile aFile(aFileName); //以文件方式读出 if (aFile.open(QIODevice::ReadOnly | QIODevice::Text)) //以只读文本方式打开文件 { QTextStream aStream(&aFile); //用文本流读取文件 ui->plainTextEdit->clear();//清空 while (!aStream.atEnd()) { QString str=aStream.readLine();//读取文件的一行 ui->plainTextEdit->appendPlainText(str); //添加到文本框显示 fFileContent.append(str); //添加到 StringList } aFile.close();//关闭文件 this->LabCurFile->setText("当前文件:"+aFileName);//状态栏显示 ui->actAppend->setEnabled(true); //更新Actions的enable属性 ui->actInsert->setEnabled(true); ui->actDelete->setEnabled(true); ui->actSave->setEnabled(true); iniModelFromStringList(fFileContent);//从StringList的内容初始化数据模型 //设置行列自适应 ui->tableView->resizeRowsToContents(); ui->tableView->resizeColumnsToContents(); }
使用文件输入输出流保存文件
{ //打开文件 QString curPath=QCoreApplication::applicationDirPath(); //获取应用程序的路径 //调用打开文件对话框打开一个文件 QString aFileName=QFileDialog::getSaveFileName(this,"选择一个文件",curPath, "井数据文件(*.txt);;所有文件(*.*)"); if (aFileName.isEmpty()) return; //如果未选择文件,退出 QFile aFile(aFileName); //以文件方式读出 if (!aFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) //以读写文本及覆盖文本方式打开文件 return; //以文件流对文件进行操作 QTextStream stream(&aFile); QString str; ui->plainTextEdit->clear(); //获取表头数据 QStandardItem * Item; for(int i = 0; i< theModel->columnCount(); i++) { Item = theModel->horizontalHeaderItem(i); //加入两个tab符,跟之前数据保持一致 str = str + Item->text() + "\t\t"; } //写入数据 stream << str << "\n"; ui->plainTextEdit->appendPlainText(str); //获取内容 int j; //下表从0开始,因为上方已经将表头元素分开 for (int i = 0; i < theModel->rowCount(); i++) { str = ""; for (j = 0; j < theModel->columnCount() - 1; j++) { Item = theModel->item(i, j); str = str + Item->text()+ "\t\t"; } //拿到最后一列 Item = theModel->item(i, j); if(Item->checkState() == 1) str = str + "1"; else str = str + "0"; //写入数据 stream << str << "\n"; ui->plainTextEdit->appendPlainText(str); }
QItemSelectionModel
QItemSelectionModel常与QStandardItemModel连用
theModel = new QStandardItemModel(10, FixedColumnCount, this); theSelection = new QItemSelectionModel(theModel);
QItemSelectionModel主要用于获取view中选择的数据项位于model的那个位置及表格的位置
向QStandardItemModel里面插入数据
//使用Qlist对数据进行添加行 QList<QStandardItem *> itemList; QStandardItem * item; //往Model里面添加数据 for (int i = 0; i < FixedColumnCount - 1; i++) { item = new QStandardItem("000"); itemList<<item; } //获取表头元素最后一列的数据 QString str = theModel->headerData(theModel->columnCount() -1, Qt::Horizontal,Qt::DisplayRole).toString(); //设置最后一行 item = new QStandardItem(str); item->setCheckState(Qt::Checked); itemList<<item; int curRow = theSelection->currentIndex().row(); //在Model最后一行添加数据 theModel->insertRow(curRow,itemList); //重新设置最后一行的选择模式 theSelection->clearSelection(); QModelIndex index = theModel->index(curRow, 0); theSelection->setCurrentIndex(index,QItemSelectionModel::Select);
自定义代理
使用代理必须实现以下几个函数:
•createEditor():创建用于编辑模型数据的widget组件,如QSpinBox,QComboBox。
•setEditorData():从数据模型获取数据,供widget组件进行编辑 。
•setModelData():将widget上的数据更新到数据模型。
•updateEditorGeometry():用于给widget组件设置一个合适的大小。
QStyledItemDelegate为代理类,如果想要实现代理,需要继承这个类,按f2进去可以了解要代理的部分,主要包括painting、editing、editor factory
将QlineEdit通过代理换成QSpinBox
//创建用于编辑模型数据的widget组件 QWidget *QIntDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QSpinBox * editor = new QSpinBox(parent); //设置QSpinbox的属性 editor->setMinimum(0); editor->setMaximum(1000); editor->setFrame(false); return editor; } //从数据模型获取数据,供widget组件进行编辑 void QIntDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { //通过index获取model 在通过model获取数据 int value = index.model()->data(index, Qt::EditRole).toInt(); //将类型转换为QSpinbox类型 QSpinBox * spinbox = static_cast<QSpinBox *>(editor); //设置值 spinbox->setValue(value); } //将widget上的数据更新到数据模型 void QIntDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { //将类型转换为QSpinbox类型 QSpinBox * spinbox = static_cast<QSpinBox *>(editor); //拿到现在的取值 spinbox->interpretText(); //设置model int value = spinbox->value(); model->setData(index, value, Qt::EditRole); } //用于给widget组件设置一个合适的大小 void QIntDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { //设置大小 editor->setGeometry(option.rect); }
写好代理类之后通过在tableview(视图)上设置即可使用
QIntDelegate intSpinDelegate;//设置自定义代理 //调用代理 //为第0列设置自定义代理 ui->tableView->setItemDelegateForColumn(0, &intSpinDelegate);
Qt对话框
标准对话框
QFileDialog
//选择单个文件 QString curPath=QDir::currentPath();//获取系统当前目录 // QString curPath=QCoreApplication::applicationDirPath(); //获取应用程序的路径 QString dlgTitle="选择一个文件"; //对话框标题 QString filter="文本文件(*.txt);;图片文件(*.jpg *.gif *.png);;所有文件(*.*)"; //文件过滤器 QString aFileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter); if (!aFileName.isEmpty()) ui->plainTextEdit->appendPlainText(aFleName);
QColorDialog
//设置QplaintTextEdit字体颜色 QPalette pal = ui->plainTextEdit->palette(); QColor inicolor = pal.color(QPalette::Text); //通过QColorDialog选择的颜色返回出来 inicolor为初始的颜色 QColor color = QColorDialog::getColor(inicolor, this, "选择颜色"); //将获取的样式设置到QplainTextEdit中 if(!color.isValid()) return; pal.setColor(QPalette::Text, color); ui->plainTextEdit->setPalette(pal);
QFontDialog
//设置字体 bool ok = false; QFont iniFont = ui->plainTextEdit->font(); //第一个参数如果选择成功 则返回true 否则返回false QFont font = QFontDialog::getFont(&ok, iniFont, this, "选择字体"); //为QPliantTextEdit设置选择的字体 if(!ok) return; ui->plainTextEdit->setFont(font);
输入对话框
字符输入对话框
//输入字符串 QString dlgTitle="输入文字对话框"; QString txtLabel="请输入文件名"; QString defaultInput="新建文件.txt"; QLineEdit::EchoMode echoMode=QLineEdit::Normal;//正常文字输入 // QLineEdit::EchoMode echoMode=QLineEdit::Password;//密码输入 bool ok=false; QString text = QInputDialog::getText(this, dlgTitle,txtLabel, echoMode,defaultInput, &ok);
整形输入对话框
//输入整数 QString dlgTitle="输入整数对话框"; QString txtLabel="设置字体大小"; int defaultValue=ui->plainTextEdit->font().pointSize(); //现有字体大小 int minValue=6, maxValue=50,stepValue=1; //范围,步长 bool ok=false; int inputValue = QInputDialog::getInt(this, dlgTitle,txtLabel, defaultValue, minValue,maxValue,stepValue,&ok); if (ok) //是否确认输入 { QFont font=ui->plainTextEdit->font(); font.setPointSize(inputValue); ui->plainTextEdit->setFont(font); }
浮点数输入对话框
//输入浮点数 QString dlgTitle="输入浮点数对话框"; QString txtLabel="输入一个浮点数"; float defaultValue=3.13; float minValue=0, maxValue=10000; //范围 int decimals=2;//小数点位数 bool ok=false; float inputValue = QInputDialog::getDouble(this, dlgTitle,txtLabel, defaultValue, minValue,maxValue,decimals,&ok); if (ok) //确认选择 { QString str=QString::asprintf("输入了一个浮点数:%.2f",inputValue); ui->plainTextEdit->appendPlainText(str); }
条目输入对话框
//条目选择输入 QStringList items; //ComboBox 列表的内容 items <<"优秀"<<"良好"<<"合格"<<"不合格"; QString dlgTitle="条目选择对话框"; QString txtLabel="请选择级别"; int curIndex=0; //初始选择项 bool editable=true; //ComboBox是否可编辑 bool ok=false; QString text = QInputDialog::getItem(this, dlgTitle,txtLabel,items,curIndex,editable,&ok); if (ok && !text.isEmpty()) ui->plainTextEdit->appendPlainText(text);
标准消息框
Question消息框
QString dlgTitle="Question消息框"; QString strInfo="文件已被修改,是否保存修改?"; QMessageBox::StandardButton defaultBtn=QMessageBox::NoButton; //缺省按钮 QMessageBox::StandardButton result;//返回选择的按钮 result=QMessageBox::question(this, dlgTitle, strInfo, QMessageBox::Yes|QMessageBox::No |QMessageBox::Cancel, defaultBtn); if (result==QMessageBox::Yes) ui->plainTextEdit->appendPlainText("Question消息框: Yes 被选择"); else if(result==QMessageBox::No) ui->plainTextEdit->appendPlainText("Question消息框: No 被选择"); else if(result==QMessageBox::Cancel) ui->plainTextEdit->appendPlainText("Question消息框: Cancel 被选择"); else ui->plainTextEdit->appendPlainText("Question消息框: 无选择");
information消息框
QString dlgTitle="information消息框"; QString strInfo="文件已经打开,字体大小已设置"; //QMessageBox::information(this, dlgTitle, strInfo);//使用缺省的按钮 QMessageBox::information(this, dlgTitle, strInfo, QMessageBox::Ok,QMessageBox::NoButton);
warning消息框
QString dlgTitle="warning 消息框"; QString strInfo="文件内容已经被修改"; QMessageBox::warning(this, dlgTitle, strInfo);
critical消息框
QString dlgTitle="critical消息框"; QString strInfo="有不明程序访问网络"; QMessageBox::critical(this, dlgTitle, strInfo);
about消息框
QString dlgTitle="about消息框"; QString strInfo="我开发的数据查看软件 V1.0 \n 保留所有版权"; QMessageBox::about(this, dlgTitle, strInfo);
自定义对话框及调用
如果想要在一个窗体调用使用另外一个窗体的元素,可以通过写public方法,通过调用public方法实现调用,需要在被调用窗体发出信号供主窗体接收,如按确认按钮发出accept()信号
首先在头文件声明方法
int rowCount();//获取对话框输入的行数 int columnCount();//获取对话框输入的列数 void setRowColumn(int row, int column); //初始对话框上两个SpinBox的值
在cpp实现方法
int QWDialogSize::rowCount() { //用于主窗口调用获得行数的输入值 return ui->spinBoxRow->value(); } int QWDialogSize::columnCount() {//用于主窗口调用获得列数的输入值 return ui->spinBoxColumn->value(); } void QWDialogSize::setRowColumn(int row, int column) { //初始化数据显示 ui->spinBoxRow->setValue(row); ui->spinBoxColumn->setValue(column); }
在另外一个窗体添加头文件,new出来然后调用
QWDialogSize *dlgTableSize=new QWDialogSize(this); //创建对话框 dlgTableSize->setRowColumn(theModel->rowCount(),theModel->columnCount()); //对话框数据初始化 int ret=dlgTableSize->exec();// 以模态方式显示对话框,用户关闭对话框时返回 DialogCode值 if (ret==QDialog::Accepted) //OK键被按下,对话框关闭,若设置了setAttribute(Qt::WA_DeleteOnClose),对话框被释放,无法获得返回值 { //OK键被按下,获取对话框上的输入,设置行数和列数 int cols=dlgTableSize->columnCount(); theModel->setColumnCount(cols); int rows=dlgTableSize->rowCount(); theModel->setRowCount(rows); } delete dlgTableSize; //删除对话框 //如果不想删除可以调用窗体的属性,实现自动删除 //dlgTableSize->setAttribute(Qt::WA_DeleteOnClose);
调用父窗体的方法
MainWindow *parWind = (MainWindow*)parentWidget(); //获取主窗口
//首先在父窗体new出来 传入this,作为父窗体 dlgLocate = new QWDialogLocate(this); //创建对话框,传递指针 dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时自动删除对话框对象,用于不需要读取返回值的对话框 //后调用父窗口的public方法 #include "mainwindow.h" void QWDialogLocate::on_btnSetText_clicked() {//定位到单元格,并设置字符串 int row=ui->spinBoxRow->value(); //行号 int col=ui->spinBoxColumn->value();//列号 MainWindow *parWind = (MainWindow*)parentWidget(); //获取主窗口 parWind->setACellText(row,col,ui->edtCaption->text()); //设置单元格文字 if (ui->chkBoxRow->isChecked()) //行增 ui->spinBoxRow->setValue(1+ui->spinBoxRow->value()); if (ui->chkBoxColumn->isChecked()) //列增 ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value()); }
多窗体应用程序设计
//窗体的一些的属性设置 void QWidget::setWindowState(Qt::WindowStates windowstate);
常量 | 意义 |
---|---|
Qt::NonModal | 无模态,不会阻止其他窗口的输入 |
Qt::WindowModal | 窗口对于其父窗口、所有的上级父窗口都是模态的 |
Qt::ApplicationModal | 窗口对整个应用程序是模态的,阻止所有窗口的输入 |
//设置窗体透明度 参数 level 是 1.0(完全不透明)至 0.0(完全透明)之间的数。窗口透明度缺省值是 1.0,即完全不透明。 void QWidget::setWindowOpacity(qreal level);
//设置窗体属性 void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on = true);
Qt:: WA_AcceptDrops | 允许窗体接收拖放来的组件 |
Qt::WA_DeleteOnClose | 窗体关闭时删除自己,释放内存 |
Qt::WA_Hover | 鼠标进入或移出窗体时产生paint事件 |
Qt:: WAAcceptTouchEvents | 窗体是否接受触屏事件 |
void QWidget::setWindowFlags(Qt::WindowFlags type);
表示窗体类型的常量 | |
---|---|
Qt::Widget | 这是 QWidget 类的缺省类型。这种类型的窗体,如果它有父窗体,就作为父窗 体的子窗体;否则就作为一个独立的窗口 |
Qt::Window | 表明这个窗体是一个窗口,通常具有窗口的边框、标题栏,而不管它是否有父窗体 |
Qt::Dialog | 表明这个窗体是一个窗口,并且要显示为对话框(例如在标题栏没有最小化、 最大化按钮)。这是 QDialog 类的缺省类型 |
Qt::Popup | 表明这个窗体是用作弹出式菜单的窗体 |
Qt::Tool | 表明这个窗体是工具窗体,具有更小的标题栏和关闭按钮,通常作为工具栏的 窗体 |
Qt::ToolTip | 表明这是用于 Tooltip 消息提示的窗体 |
Qt::SplashScreen | 表明窗体是splash屏幕,是 QSplashScreen 类的缺省类型 |
Qt::Desktop | 表明窗体是桌面,这是 QDesktopWidget 类的类型 |
Qt::SubWindow | 表明窗体是子窗体,例如 QMdiSubWindow 就是这种类型 |
控制窗体显示效果的常量 | |
---|---|
Qt::MSWindowsFixedSizeDialogHint | 在 Windows 平台上,使窗口具有更窄的边框,用于固定大小的对话框 |
Qt::FramelessWindowHint | 创建无边框窗口 |
WindowHint要定义窗体外观定制窗体外观的常量,需要先设置 Qt::Customize | |
Qt::CustomizeWindowHint | 关闭缺省的窗口标题栏 |
Qt::WindowTitleHint | 窗口有标题栏 |
Qt::WindowSystemMenuHint | 有窗口系统菜单 |
Qt::WindowMinimizeButtonHint | 有最小化按钮 |
Qt::WindowMaximizeButtonHint | 有最大化按钮 |
Qt::WindowMinMaxButtonsHint | 有最小化、最大化按钮 |
Qt::WindowCloseButtonHint | 有关闭按钮 |
Qt::Windo wContextHelpButtonHint | 有上下文帮助按钮 |
Qt::WindowStaysOnTopHint | 窗口总是处于最上层 |
Qt::WindowStaysOnBottomHint | 窗口总是处于最下层 |
Qt::WindowTransparentForlnput | 窗口只作为输出,不接受输入 |
QMainWindow创建的时候可以使用其他窗体作为父窗体,如:
QMainWindow * testMain = new QMainWindow(this); testMain->setAttribute(Qt::WA_DeleteOnClose); testMain->setWindowTitle("多实例窗口,指定父窗口"); testMain->show();
但QWidget则一般不会使用QMainWindow作为它的父窗体,如果作为父窗体则贴在父窗体上不能移动,一般不传入this指针使用
//不加入this窗体关闭不会进行自动回收 QFormDoc * fordoc = new QFormDoc(); //设置关闭时自动删除 fordoc->setAttribute(Qt::WA_DeleteOnClose); //设置窗口标题 fordoc->setWindowTitle("基于QWidget的窗体,无父窗口,关闭时删除"); //设置窗体透明度 fordoc->setWindowOpacity(0.7); fordoc->show();
MDI应用程序设计
MDI模式的使用应加入头文件 #include "QMdiSubWindow"
//设置MDI模式 级联展开为分为几个不同窗体打开 平铺展开为几个窗体在同一个大窗体展开 void MainWindow::on_actViewMode_triggered(bool checked) { if(checked) { //设置为TableView模式 ui->mdiArea->setViewMode(QMdiArea::TabbedView); //设置tableview模式窗体可关闭 ui->mdiArea->setTabsClosable(true); //设置平铺展开和级联展开不可用 ui->actCascade->setEnabled(false); ui->actTile->setEnabled(false); } else { //设置为窗体模式(默认模式) ui->mdiArea->setViewMode(QMdiArea::SubWindowView); //设置平铺展开和级联展开可用 ui->actCascade->setEnabled(true); ui->actTile->setEnabled(true); } } //这两种模式在QMdiArea::SubWindowView(窗体模式)进行使用 void MainWindow::on_actCascade_triggered() { //设置QMdiArea级联模式 ui->mdiArea->cascadeSubWindows(); } void MainWindow::on_actTile_triggered() { //设置QMdiArea平铺模式 ui->mdiArea->tileSubWindows(); } //当当前选择的Widget发生改变时,状态栏显示文件地址 void MainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1) { //如果没有窗口的话 设置剪切复制等为不可用 清空状态栏的内容 if(ui->mdiArea->subWindowList().count() == 0) { ui->actCopy->setEnabled(false); ui->actCut->setEnabled(false); ui->actFont->setEnabled(false); ui->actPaste->setEnabled(false); ui->statusBar->clearMessage(); } else { //显示主窗口的文件名 FormDoc * mdoc = (FormDoc *)ui->mdiArea->activeSubWindow()->widget(); ui->statusBar->showMessage(mdoc->GetcurrentFileName()); } }
//打开文件 FormDoc为自定义QWidget void MainWindow::on_actDoc_Open_triggered() { bool needNew = false; FormDoc * mdoc; //获取QMdiArea的个数 if(ui->mdiArea->subWindowList().count() > 0) { // ui->mdiArea->activeSubWindow()获取的是QMdiSubWindow对象 //如果想要获取相应的Qwidget 需要使用ui->mdiArea->activeSubWindow()->widget();后进行类型转换 mdoc = (FormDoc*)ui->mdiArea->activeSubWindow()->widget(); needNew = mdoc->isFileOpened(); } else { needNew = true; } if(needNew) { mdoc = new FormDoc(this); //向获取QMdiArea里面添加Widget ui->mdiArea->addSubWindow(mdoc); } QString fileName = QFileDialog::getOpenFileName(this, "open", "", "C程序文件(.h *cpp);;所有文件" ); mdoc->loadFromFile(fileName); mdoc->show(); ui->actCopy->setEnabled(true); ui->actCut->setEnabled(true); ui->actFont->setEnabled(true); ui->actPaste->setEnabled(true); }
//加载文件 使用QTextStream对文件进行读取 void FormDoc::loadFromFile(QString &aFileName) { QFile file(aFileName); //QIODevice::ReadOnly设置为只读 QIODevice::Text设置为文本格式,会自动处理\n \t等字符 if(file.open(QIODevice::ReadOnly)|QIODevice::Text) { //使用QTextStream对文本进行操作 QTextStream stream(&file); //填充QPlainText ui->plainTextEdit->clear(); ui->plainTextEdit->setPlainText(stream.readAll()); //获取文件的路径和名称 mCurrentFile = aFileName; QFileInfo fileinfo(aFileName); QString str = fileinfo.fileName(); setWindowTitle(str); //设置为true,代表文档已经是打开的状态 m_isOpen = true; } }
SPlash和登录窗口
Qt有一个QSplashScreen类可以实现Splash窗口的功能,它提供了载入图片,自动设置窗口无边框效果等功能。
QSettings配置表的存入和读取
#include <QSettings> //写入注册表 void DialogLogin::writeSettings() { //使用QSettings将信息写入注册表中 第一个参数为库名 第二个参数为表名 QSettings settings("LF-QT", "Simple6_5"); //为注册表添加数据 settings.setValue("Username", m_user); settings.setValue("PSWD", m_pswd); settings.setValue("saved", ui->chkBoxSave->isChecked());//是否保存 } //读取配置表的数据 void DialogLogin::readSettings() { QSettings settings("LF-QT", "Simple6_5"); //获取配置表数据 进行类型转换 //第一个参数为关键值 也就是SetValue的第一个参数,第二个参数为默认值 bool saved = settings.value("saved", false).toBool(); m_user = settings.value("Username", "user").toString(); //设置默认密码 进行加密处理 QString defaultPSWD = encrypt("123456"); m_pswd = settings.value("PSWD", defaultPSWD).toString(); //如果勾选了 自动填充账号 if(saved) { ui->editUser->setText(m_user); } ui->chkBoxSave->setChecked(saved); }
使用哈希算法对md5进行加密
#include <QCryptographicHash> //对密码进行加密 QString DialogLogin::encrypt(const QString &str) { QByteArray btArray; btArray.append(str); //使用哈希算法进行加密 加密格式为md5类型 QCryptographicHash hash(QCryptographicHash::Md5); hash.addData(btArray); //接收加密后的结果 并进行十六进制类型转换存储 QByteArray resultArray = hash.result(); QString resultmd5 = resultArray.toHex(); return resultmd5; }
设置QDialog属性
ui->editPSWD->setEchoMode(QLineEdit::Password); //密码输入编辑框设置为密码输入模式 this->setAttribute(Qt::WA_DeleteOnClose);//设置为关闭时删除 this->setWindowFlags(Qt::SplashScreen); //设置为SplashScreen, 窗口无边框,不在任务栏显示
使用鼠标事件使得无标头的QDialog可以进行移动
#include <QMouseEvent> //头文件 protected: //用于鼠标拖动窗口的鼠标事件操作 void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); bool m_moving=false;//表示窗口是否在鼠标操作下移动 QPoint m_lastPos; //上一次的鼠标位置 //cpp文件 void DialogLogin::mousePressEvent(QMouseEvent *event) { if(event->buttton == Qt::LeftButton) { m_moving = true; //记录移动的距离 globalPos()为鼠标点击后的位置到(0,0)点距离 pos()为DialogLogin窗体到(0,0)点距离 m_lastPos = event->globalPos() - pos(); } return DialogLogin::mouseMoveEvent(event); } void DialogLogin::mouseMoveEvent(QMouseEvent *event) { if(m_moving && (event->buttton == Qt::LeftButton)) { move(event->globalPos() - m_lastPos); m_lastPos = event->globalPos() - pos(); } } void DialogLogin::mouseReleaseEvent(QMouseEvent *event) { m_moving = false; }
文本文件读写
QIODevice::ReadOnly | 以只读方式打开 |
QIODevice::WriteOnly | 以只写方式打开 |
QIODevice::ReadWrite | 以读写方式打开 |
QIODevice::Append | 新增加的内容将被追加到文件末尾 |
QIODevice::Truncate | 以重写的方式打开,原有内容会被删除 |
QIODevice::Text | 在读取时,将行结束符转换成 \n;在写入时,将行结束符转换成本地格式,例如 Win32 平台上是 \r\n |
QFile IODevice读写文件
#include <QFileDialog> //使用QFile读取文件 void MainWindow::on_actOpen_IODevice_triggered() { //设置QFileDialog 属性 获得打开文件的文件路径 QString curPath = QCoreApplication::applicationDirPath(); QString dlgTitle = "打开文件"; QString filter = "程序(*.h *.cpp);;文本( *.txt);; 所有文件(*.*)"; QString fileName = QFileDialog::getOpenFileName(this, curPath, dlgTitle, filter); if(fileName.isEmpty()) return; //使用QFile IODevice对文件进行读取 QFile file(fileName); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { ui->plainTextEditIODevice->setPlainText(QString::fromLocal8Bit(file.readAll())); file.close(); ui->tabWidget->setCurrentIndex(0); } } //使用QFile另存为文件 即写文件 void MainWindow::on_actSave_IODevice_triggered() { //设置QFileDialog 属性 获得打开文件的文件路径 QString curPath = QCoreApplication::applicationDirPath(); QString dlgTitle = "打开文件"; QString filter = "程序(*.h);;文本( *.txt);; 所有文件(*.*)"; QString fileName = QFileDialog::getSaveFileName(this, curPath, dlgTitle, filter); if(fileName.isEmpty()) return; //打开文件进行写操作 QFile file(fileName); if(file.open(QIODevice::WriteOnly | QIODevice::Text)) { //获取QPlainText的内容 并进行类型转换后写入文件内 QString str = ui->plainTextEditIODevice->toPlainText(); //写入文件 QByteArray btyArray = str.toUtf8(); file.write(btyArray, btyArray.length()); //关闭文件 file.close(); //设置QtabWidget当前索引 ui->tabWidget->setCurrentIndex(0); } }
QTextSteam读写文件
#include <QFileDialog> #include <QTextStream> //使用QTextStream进行读取 void MainWindow::on_actOpen_TextStream_triggered()