




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
QT5开发及实例(第5版)第9章Qt5模型/视图及实例——模型/视图架构01基本概念基本概念模型/视图架构的理念其实源于Web开发领域的MVC。MVC是起源于Smalltalk的一种与用户界面相关的设计模式,它包括3个基本元素:表示数据的模型M(Model)、表示界面的视图V(View)以及管理用户界面操作逻辑的控制器C(Controller)。Qt的模型/视图架构可分为三部分:模型M(Model)、视图V(View)和代理D(Delegate)。其中,模型直接与数据源通信,并为程序其他部件提供数据接口,它从原始数据提取所需内容供给各类视图组件去显示或编辑;视图也就是程序界面上以各种丰富多样的形式展示数据的控件,它们从模型中获得所要引用数据条目项的模型索引(ModelIndex),再以索引方式获取和呈现各自的显示内容;而代理则负责绘制界面上的数据条目,当用户编辑条目时,它就直接与模型进行通信,它们之间的互动关系如图。02实
现
类实
现
类1.模型类模型/视图架构中的所有模型都基于抽象基类QAbstractItemModel,此类针对各种视图组件和代理都有与之相适应的数据存取接口,由此而派生出一系列不同用途的子模型类,如图。实
现
类其中,各个主要方面用途的类及其子类说明如下。文本、字符串列表:QAbstractListModel类是列表模型的抽象基类,通常程序界面上的列表项数据内容是以文本或字符串形式出现的,在Qt中用QStringList结构存储,其对应的模型类QStringListModel就是从QAbstractListModel继承而来。数据库相关:数据库的数据在界面上常以表格展示,由表格模型抽象类QAbstractTableModel派生出QtSql模块用户接口层的三个类QSqlQueryModel、QSqlTableModel及QSqlRelationalTableModel,分别实现对SQL语句查询结果数据、表数据及关系表外键数据的读写。文件系统和目录:QDirModel类是操作系统目录数据的存储模型;QFileSystemModel用于存储文件系统信息。代理:QAbstractProxyModel与QProxyModel类分别是代理模型的抽象类及其实现类。实
现
类2.视图类模型/视图架构中的所有视图都基于抽象基类QAbstractItemView,视图及相关类继承的层次结构如图。下面就这几个视图类所对应组件的用途加以说明。QListView:列表视图。用于显示单列的列表数据,如组合框、下拉列表框控件的选项。QTableView:表格视图。用于显示表格形式的数据,常用于在界面上展示数据库中的表或视图的记录内容。QTreeView:树状视图。用于显示可展开/折叠的多层次节点数据项,例如,浏览本地计算机操作系统的目录树。QColumnView:列视图。当在界面上以多个并排级联列表的形式展示树状层次结构数据时,每一级列表就是一个QColumnView。QHeaderView:表头视图。提供表格控件的行表头或列表头内容显示。实
现
类3.代理类模型/视图架构中的所有代理都基于抽象基类QAbstractItemDelegate,此类由QItemDelegate和QStyledItemDelegate类继承。其中,QItemDelegate类由表示数据库中关系代理的QSqlRelationalDelegate类继承。QT5开发及实例(第5版)第9章Qt5模型/视图及实例——常用模型/视图组件实例01表格视图/模型及实例1.表格视图组件:QTableView2.表格模型3.实例表格视图/模型及实例1.表格视图组件:QTableView表格视图QTableView组件用于在程序界面上展示二维数据表格,它常与Qt通用的标准项模型QStandardItemModel配合使用,通过setItem(i,j,项)方法将标准项QStandardItem的实例对象添加到表格正文内容的第i行第j列中,调用setModel(model)方法将模型关联进表格视图。QTableView常用方法如下:(1)rowHeight():获得表中每一行的高度。(2)columnWidth():获得表中每一列的宽度。(3)showGrid():显示一个网格。(4)stretchLastSection():展开表中的单元格。(5)hideRow()和hideColumn():隐藏行和列。(6)showRow()和showColumn():显示行和列。(7)selectRow()和selectColumn():选择行和列。(8)resizeColumnsToContents()或resizeRowsToContents():根据每个列或行的空间需求分配可用空间。在模型/视图架构中还有一个表头视图QHeaderView可用于显示和控制QTableView的表头,其方法如下:(1)verticalHeader():获得垂直表头。(2)horizontalHeader():获得水平表头。(3)hide():隐藏表头。表格视图/模型及实例2.表格模型QTableView通过绑定模型来更新其上的内容,可用的模型如表。模
型作
用QStringListModel存储一组字符串QStandardItemModel存储任意层次结构的数据QDirModel对文件系统进行封装QSqlQueryModel对SQL的查询结果集进行封装QSqlTableModel对SQL中的表格进行封装QSqlRelationalTableModel对带有外键的SQL表格进行封装QSortFilterProxyModel对模型中的数据进行排序或过滤表格视图/模型及实例3.实例【例】(简单)(CH901)用QStandardItemModel模型存储课程信息,在QTableView表格视图中显示。以“直接编写代码”(即取消勾选“Generateform”复选框)方式创建Qt项目,项目名tableView,“ClassInformation”页基类选“QWidget”。代码如下(tableView.cpp):运行程序,显示如图。02树状视图/模型及实例1.树状视图组件:QTreeView2.实例树状视图/模型及实例1.树状视图组件:QTreeView树状视图QTreeView组件用于显示具有层次结构的节点数据项,也常与标准项模型一起使用,QStandardItemModel的实例对象model通过appendRow(QStandardItem*dotItem1)方法将标准项实例对象dotItem1添加进第一个节点,再调用setModel(model)方法将模型关联进树状视图。使用树状视图,可以先创建一个标准项作为顶层对象,然后设置它的属性,再创建子项添加到该项下……每一级均是如此,最后将顶层对象加入创建的树状视图中。2.实例【例】(难度一般)(CH902)创建南京师范大学及其学院、系树视图。以“直接编写代码”(即取消勾选“Generateform”复选框)方式创建Qt项目,项目名treeView,“ClassInformation”页基类选“QMainWindow”,类名命名为“mainWin”。代码如下(treeView.cpp):树状视图/模型及实例运行程序,如图。03文件目录浏览器实例文件目录浏览器实例【例】(简单)(CH903)实现一个简单的文件目录浏览器,完成效果如图。以“直接编写代码”(即取消勾选“Generateform”复选框)方式创建Qt项目,项目名DirModeEx,“ClassInformation”页基类选“QMainWindow”。在源文件main.cpp中编写代码如下。04自定义模型实例自定义模型实例【例】(难度一般)(CH904)实际应用中,常常将一些重复的文字字段用数值代码保存,使用时再通过关联操作(如外键)来获取其真实的内容,此种方法可有效避免数据存储的冗余。试开发一个通过将数值代码映射为文字的模型来保存不同军种的各种武器信息,实现效果如图。自定义模型实例开发步骤如下。(1)在项目中创建ModelEx类继承自QAbstractTableModel类,其头文件modelex.h的代码如下。(2)在ModelEx类的构造函数(位于源文件modelex.cpp)中编写代码如下:#include"modelex.h"ModelEx::ModelEx(QObject*parent):QAbstractTableModel(parent){armyMap[1]="空军";armyMap[2]="海军";armyMap[3]="陆军";armyMap[4]="海军陆战队";weaponTypeMap[1]="轰炸机";weaponTypeMap[2]="战斗机";weaponTypeMap[3]="航空母舰";weaponTypeMap[4]="驱逐舰";weaponTypeMap[5]="直升机";weaponTypeMap[6]="坦克";weaponTypeMap[7]="两栖攻击舰";weaponTypeMap[8]="两栖战车";populateModel();}自定义模型实例最后的populateModel()函数完成表格数据的初始化填充,具体实现代码如下:voidModelEx::populateModel(){header<<"军种"<<"种类"<<"武器";army<<1<<2<<3<<4<<2<<4<<3<<1;weaponType<<1<<3<<5<<7<<4<<8<<6<<2;weapon<<"B-2"<<"尼米兹级"<<"阿帕奇"<<"黄蜂级"<<"阿利伯克级"<<"AAAV"<<"M1A1"<<"F-22";}自定义模型实例(3)实现父类虚函数用户自定义的模型类必须实现父类中所有的虚函数,一共4个虚函数,分别实现如下。①虚函数rowCount()返回模型的行数,代码为:intModelEx::rowCount(constQModelIndex&parent)const{returnarmy.size();}②虚函数columnCount()函数返回模型的列数。因为模型的列固定为3,所以直接返回3:intModelEx::columnCount(constQModelIndex&parent)const{return3;}自定义模型实例③虚函数data()返回指定索引的数据,即将数值映射为文字,代码如下:QVariantModelEx::data(constQModelIndex&index,introle)const{if(!index.isValid())returnQVariant();if(role==Qt::DisplayRole){switch(index.column()){case0:returnarmyMap[army[index.row()]];break;case1:returnweaponTypeMap[weaponType[index.row()]];break;case2:returnweapon[index.row()];default:returnQVariant();}}returnQVariant();}自定义模型实例见表列出了Item主要的角色及其描述。常
量描
述Qt::DisplayRole显示文字Qt::DecorationRole绘制装饰数据(通常是图标)Qt::EditRole在编辑器中编辑的数据Qt::ToolTipRole工具提示Qt::StatusTipRole状态栏提示Qt::WhatsThisRoleWhat’sThis文字Qt::SizeHintRole尺寸提示Qt::FontRole默认代理的绘制使用的字体Qt::TextAlignmentRole默认代理的对齐方式Qt::BackgroundRole默认代理的背景画刷Qt::ForegroundRole默认代理的前景画刷Qt::CheckStateRole默认代理的检查框状态Qt::UserRole用户自定义数据的起始位置自定义模型实例④虚函数headerData()返回固定的表头数据,设置水平表头的标题,具体代码如下:QVariantModelEx::headerData(intsection,Qt::Orientationorientation,introle)const{if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)returnheader[section];returnQAbstractTableModel::headerData(section,orientation,role);}自定义模型实例(4)最后,在源文件main.cpp中将自定义的模型与表格视图关联,代码如下:#include<QApplication>#include"modelex.h"#include<QTableView>intmain(intargc,char*argv[]){QApplicationa(argc,argv);ModelExmodelEx; //自定义模型QTableViewview; //表格视图view.setModel(&modelEx);view.setWindowTitle("自定义模型");view.resize(400,400);view.show();returna.exec();}自定义模型实例(5)运行程序,显示出自定义模型中数据的效果如图。QT5开发及实例(第5版)第9章Qt5模型/视图及实例——代理及应用实例01代理概念及开发步骤1.什么是代理2.代理开发步骤代理概念及开发步骤1.什么是代理从前面的实例可见,表格视图QTableView可以支持用户对表单元格中的内容进行编辑,但是Qt默认的单元格编辑控件只有文本框(QLineEdit)一种(图),而实际应用需求是多样的,可能更适宜采用其他类型的控件来接受用户输入,例如,想要限定单元格的内容只能从几个固定选项中选取,就要用下拉列表框(QComboBox)(图),Qt的模型/视图架构通过一种叫做“代理”的机制来实现此类功能。
代理概念及开发步骤2.代理开发步骤(1)创建代理类用QtCreator打开要开发代理的项目,右击项目名,选“添加新文件...”,弹出对话框选择新建一个“C++Class”类模板,点“Choose”按钮,在接下来的向导界面上输入自定义代理类的名称及要继承的代理基类,勾选“AddQ_OBJECT”,如图9.10所示。代理概念及开发步骤(2)实现代理函数无论是从QItemDelegate还是QStyledItemDelegate类继承创建的代理类,要实现代理功能,都必须重写4个基本的函数。先在自定义代理类的头文件中声明这4个函数的原型,代码如下:......#include<QItemDelegate(或QStyledItemDelegate)>#include<代理对应的Qt控件库>
class自定义代理类:publicQItemDelegate(或QStyledItemDelegate){Q_OBJECTpublic:ComboDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const; //函数1voidsetEditorData(QWidget*editor,constQModelIndex&index)const; //函数2voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const; //函数3voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const; //函数4};......代理概念及开发步骤(3)关联到视图开发好代理类后,就可以在界面视图开发中为表格的任一列设置代理,将控件关联到这列上的单元格,使用setItemDelegateForColumn函数,语句如下:视图对象.setItemDelegateForColumn(列号,&代理类对象);其中,列号从0开始,通常在视图的模型设置setModel函数之后调用这条语句将代理与视图关联,这样就可在所设列的单元格中使用代理类的控件来编辑其内容。02代理应用实例1.开发视图界面2.实现日历编辑框3.实现下拉列表框4.实现数字选择框代理应用实例【例】(难度中等)(CH905)针对如图的表格视图数据,开发几种代理类分别以不同类型的控件编辑表格中不同列的数据内容。代理应用实例以“直接编写代码”(即取消勾选“Generateform”复选框)方式创建Qt项目,项目名DateDelegate,“ClassInformation”页基类选“QMainWindow”。开发步骤如下。1.开发视图界面(1)在源文件main.cpp中编写代码如下。(2)在QtCreator中选择菜单“构建”→“构建项目"DateDelegate"”项,生成Debug目录。(3)按照图的格式编辑本例视图数据来源的文件test.txt,将其保存到项目Debug目录下,然后运行程序。代理应用实例2.实现日历编辑框想要通过手动选择日期的方式实现对生日的录入编辑,需要定义一个代理类来实现日历编辑框QDateTimeEdit,如下。(1)创建代理类在项目中创建一个代理类DateDelegate继承自QItemDelegate类。(2)实现代理函数在代理类头文件datedelegate.h中声明4个代理函数,如下:#include<QItemDelegate>classDateDelegate:publicQItemDelegate{Q_OBJECTpublic:DateDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const;voidsetEditorData(QWidget*editor,constQModelIndex&index)const;voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const;voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const;};代理应用实例在代理类源文件datedelegate.cpp中编写实现这4个函数的代码,具体如下。①createEditor()函数的实现代码:QWidget*DateDelegate::createEditor(QWidget*parent,constQStyleOptionViewItem&/*option*/,constQModelIndex&/*index*/)const{QDateTimeEdit*editor=newQDateTimeEdit(parent); //(a)editor->setDisplayFormat("yyyy-MM-dd"); //(b)editor->setCalendarPopup(true); //(c)editor->installEventFilter(const_cast<DateDelegate*>(this)); //(d)returneditor;}②setEditorData()函数的实现代码:voidDateDelegate::setEditorData(QWidget*editor,constQModelIndex&index)const{QStringdateStr=index.model()->data(index).toString(); //(a)QDatedate=QDate::fromString(dateStr,Qt::ISODate); //(b)QDateTimeEdit*edit=static_cast<QDateTimeEdit*>(editor); //(c)edit->setDate(date); //设置控件的显示数据}代理应用实例③setModelData()函数的实现代码:voidDateDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const{QDateTimeEdit*edit=static_cast<QDateTimeEdit*>(editor); //(a)QDatedate=edit->date(); //(b)model->setData(index,QVariant(date.toString(Qt::ISODate))); //(c)} ④updateEditorGeometry()函数的实现代码:voidDateDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const{editor->setGeometry(option.rect);}代理应用实例(3)关联到视图在main.cpp文件中添加代理类头文件包含:#include"datedelegate.h"在语句tableView.setModel(&model);后面添加如下代码:DateDelegatedateDelegate;tableView.setItemDelegateForColumn(1,&dateDelegate);此时运行程序,双击表格第2列的任一单元格,将出现如图的日历编辑框,可从中选择修改生日日期。代理应用实例3.实现下拉列表框想要通过下拉列表选择职业类型,需要定义一个代理类来实现下拉列表框QComboBox,如下。(1)创建代理类在项目中创建一个代理类ComboDelegate继承自QItemDelegate类。(2)实现代理函数在代理类头文件combodelegate.h中声明4个代理函数,如下:#include<QItemDelegate>classComboDelegate:publicQItemDelegate{Q_OBJECTpublic:ComboDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const;voidsetEditorData(QWidget*editor,constQModelIndex&index)const;voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const;voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const;};代理应用实例在代理类源文件combodelegate.cpp中编写实现这4个函数的代码,具体如下。①createEditor()函数的实现代码:QWidget*ComboDelegate::createEditor(QWidget*parent,constQStyleOptionViewItem&/*option*/,constQModelIndex&/*index*/)const{QComboBox*editor=newQComboBox(parent);editor->addItem("工人");editor->addItem("农民");editor->addItem("医生");editor->addItem("律师");editor->addItem("军人");editor->installEventFilter(const_cast<ComboDelegate*>(this));returneditor;}代理应用实例②setEditorData()函数的实现代码:voidComboDelegate::setEditorData(QWidget*editor,constQModelIndex&index)const{QStringstr=index.model()->data(index).toString();QComboBox*box=static_cast<QComboBox*>(editor);inti=box->findText(str);box->setCurrentIndex(i);}代理应用实例③setModelData()函数的实现代码:voidComboDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const{QComboBox*box=static_cast<QComboBox*>(editor);QStringstr=box->currentText();model->setData(index,str);}④updateEditorGeometry()函数的实现代码:voidComboDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&/*index*/)const{editor->setGeometry(option.rect);}代理应用实例(3)关联到视图在main.cpp文件中添加代理类头文件包含:#include"combodelegate.h"在语句tableView.setModel(&model);的后面添加以下代码:ComboDelegatecomboDelegate;tableView.setItemDelegateForColumn(2,&comboDelegate);此时运行程序,双击表格第3列的任一单元格,显示如图的下拉列表。代理应用实例4.实现数字选择框想要通过上下箭头调整最后一列的收入值,需要定义一个代理类来实现数字选择框QSpinBox,如下。(1)创建代理类在项目中创建一个代理类SpinDelegate继承自QItemDelegate类。(2)实现代理函数在代理类头文件spindelegate.h中声明4个代理函数,如下:#include<QItemDelegate>classSpinDelegate:publicQItemDelegate{Q_OBJECTpublic:SpinDelegate(QObject*parent=0);QWidget*createEditor(QWidget*parent,constQStyleOptionViewItem&option,constQModelIndex&index)const;voidsetEditorData(QWidget*editor,constQModelIndex&index)const;voidsetModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const;voidupdateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&index)const;};代理应用实例在代理类源文件spindelegate.cpp中编写实现这4个函数的代码,具体如下。①createEditor()函数的实现代码:QWidget*SpinDelegate::createEditor(QWidget*parent,constQStyleOptionViewItem&/*option*/,constQModelIndex&/*index*/)const{QSpinBox*editor=newQSpinBox(parent);editor->setRange(0,10000);editor->installEventFilter(const_cast<SpinDelegate*>(this));returneditor;}②setEditorData()函数的实现代码:voidSpinDelegate::setEditorData(QWidget*editor,constQModelIndex&index)const{intvalue=index.model()->data(index).toInt();QSpinBox*box=static_cast<QSpinBox*>(editor);box->setValue(value);}代理应用实例③setModelData()函数的实现代码:voidSpinDelegate::setModelData(QWidget*editor,QAbstractItemModel*model,constQModelIndex&index)const{QSpinBox*box=static_cast<QSpinBox*>(editor);intvalue=box->value();model->setData(index,value);}④updateEditorGeometry()函数的实现代码:voidSpinDelegate::updateEditorGeometry(QWidget*editor,constQStyleOptionViewItem&option,constQModelIndex&/*index*/)const{editor->setGeometry(option.rect);}代理应用实例(3)关联到视图在main.cpp文件中添加代理类头文件包含:#include"spindelegate.h"在语句tableView.setModel(&model);的后面添加内容如下:SpinDelegatespinDelegate;tableView.setItemDelegateForColumn(3,&spinDelegate);此时运行程序,双击表格第4列的任一单元格,出现带箭头的数字选择框如图,可上下翻动调整收入值。QT5开发及实例(第5版)第9章Qt5模型/视图及实例——综合实例:汽车信息管理系统综合实例:汽车信息管理系统【例】(较难)(CH906)开发一个汽车信息管理系统,界面上用多个模型和视图以主从配合的方式呈现丰富的信息,如图。01开发前的准备1.安装MySQL2.创建数据库3.编译MySQL驱动开发前的准备1.安装MySQL从Oracle官网下载MySQL安装包可执行程序,双击启动向导,按照向导界面指引安装;或者下载MySQL压缩包,手动编写配置文件,通过Windows命令行安装MySQL服务。2.创建数据库安装好MySQL后,再安装一个可视化操作工具(笔者用的是NavicatPremium),创建数据库carview,其中创建两个表:factory(汽车制造商表)和cars(汽车表),并录入测试用数据。在NavicatPremium中新建一个查询,通过执行以下SQL语句来完成上述操作:(1)创建factory表、录入数据:CREATETABLEfactory(idintPRIMARYKEY,manufactoryvarchar(40),addressvarchar(40));INSERTINTOfactoryVALUES(1,'一汽大众','长春');INSERTINTOfactoryVALUES(2,'二汽神龙','武汉');INSERTINTOfactoryVALUES(3,'上海大众','上海');开发前的准备(2)创建cars表、录入数据:CREATETABLEcars(caridintPRIMARYKEY,namevarchar(50),factoryidint,yearint,detailsjsonNULL,FOREIGNKEY(factoryid)REFERENCESfactory(id));INSERTINTOcarsVALUES(1,'奥迪A6',1,2023,null);INSERTINTOcarsVALUES(2,'捷达',1,2011,null);INSERTINTOcarsVALUES(3,'宝来',1,2018,null);INSERTINTOcarsVALUES(4,'毕加索',2,2017,null);INSERTINTOcarsVALUES(5,'富康',2,2022,null);INSERTINTOcarsVALUES(6,'标致307',2,2019,null);INSERTINTOcarsVALUES(7,'桑塔纳',3,2013,null);INSERTINTOcarsVALUES(8,'帕萨特',3,2018,null);开发前的准备(3)在cars表JSON字段中录入车型详细信息数据:UPDATEcarsSETdetails=JSON_OBJECT("01","排量:2393ml","02","价格:43.26万元","03","排放:欧4","04","油耗:7.0l(90km/h)8.3l(120km/h)","05","功率:130/6000")WHEREcarid=1;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1600ml","02","价格:8.98万元","03","排放:欧3","04","油耗:6.1l(90km/h)","05","功率:68/5800")WHEREcarid=2;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1600ml","02","价格:11.25万元","03","排放:欧3带OBD","04","油耗:6.0l(90km/h)8.1l(120km/h)","05","功率:74/6000")WHEREcarid=3;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1997ml","02","价格:15.38万元","03","排放:欧3带OBD","04","油耗:6.8l(90km/h)","05","功率:99/6000")WHEREcarid=4;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1600ml","02","价格:6.58万元","03","排放:欧3","04","油耗:6.5l(90km/h)","05","功率:65/5600")WHEREcarid=5;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1997ml","02","价格:16.08万元","03","排放:欧4","04","油耗:7.0l(90km/h)","05","功率:108/6000")WHEREcarid=6;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1781ml","02","价格:7.98万元","03","排放:国3","04","油耗:≤7.2l(90km/h)","05","功率:70/5200")WHEREcarid=7;UPDATEcarsSETdetails=JSON_OBJECT("01","排量:1984ml","02","价格:19.58万元","03","排放:欧4","04","油耗:7.1l(90km/h)","05","功率:85/5400")WHEREcarid=8;3.编译MySQL驱动如果是初次开发基于MySQL的Qt项目,需要用Qt的源码工程自行编译生成MySQL的驱动DLL库后引入开发环境02开发视图界面1.声明界面元素2.布局主界面3.创建界面元素开发视图界面1.声明界面元素主窗口MainWindow类继承自QMainWindow类,在其头文件mainwindow.h中声明了主界面上所有要显示的界面元素及其创建函数,代码如下:#include<QMainWindow>#include<QGroupBox>#include<QTableView>#include<QListWidget>#include<QLabel>classMainWindow:publicQMainWindow{Q_OBJECTpublic:MainWindow(QWidget*parent=nullptr);~MainWindow();private:QGroupBox*createFactoryGroupBox(); //创建“汽车制造商”视图组框QGroupBox*createCarGroupBox(); //创建“汽车”视图组框QGroupBox*createDetailsGroupBox(); //创建“详细信息”组框voidcreateMenuBar(); //创建操作菜单QTableView*factoryView; //汽车制造商视图QTableView*carView; //汽车视图QLabel*profileLabel; //制造商概要信息标签QLabel*titleLabel; //品牌标签QListWidget*attribList; //车型详细信息列表};开发视图界面2.布局主界面在主窗口源文件mainwindow.cpp中通过编写代码来布局汽车信息管理系统的主界面,如下。3.创建界面元素在布局界面的过程中,通过调用函数创建界面元素,调用了以下4个函数。(1)createFactoryGroupBox()函数创建界面左上区域的“汽车制造商”视图组框,代码如下:QGroupBox*MainWindow::createFactoryGroupBox(){factoryView=newQTableView; //创建汽车制造商视图factoryView->setEditTriggers(QAbstractItemView::NoEditTriggers); //禁止用户编辑汽车制造商视图factoryView->setSortingEnabled(true);factoryView->setSelectionBehavior(QAbstractItemView::SelectRows);factoryView->setSelectionMode(QAbstractItemView::SingleSelection); //设置视图选择模式为单行选择factoryView->setShowGrid(false); //不显示网格factoryView->setAlternatingRowColors(true);QGroupBox*box=newQGroupBox("汽车制造商");QGridLayout*layout=newQGridLayout;layout->addWidget(factoryView,0,0); //将视图添加进组框box->setLayout(layout);returnbox;}开发视图界面(2)createCarGroupBox()函数创建界面左下区域的“汽车”视图组框,代码如下:QGroupBox*MainWindow::createCarGroupBox(){QGroupBox*box=newQGroupBox("汽车");carView=newQTableView; //创建汽车视图carView->setEditTriggers(QAbstractItemView::NoEditTriggers);carView->setSortingEnabled(true);carView->setSelectionBehavior(QAbstractItemView::SelectRows);carView->setSelectionMode(QAbstractItemView::SingleSelection);carView->setShowGrid(false);carView->verticalHeader()->hide();carView->setAlternatingRowColors(true);QVBoxLayout*layout=newQVBoxLayout;layout->addWidget(carView,0,0); //将视图添加进组框box->setLayout(layout);returnbox;}开发视图界面(3)createDetailsGroupBox()函数创建界面右区的“详细信息”组框,代码如下:QGroupBox*MainWindow::createDetailsGroupBox(){QGroupBox*box=newQGroupBox("详细信息");profileLabel=newQLabel; //创建显示汽车制造商概要信息的标签profileLabel->setWordWrap(true);profileLabel->setAlignment(Qt::AlignBottom);titleLabel=newQLabel; //创建显示品牌的标签titleLabel->setWordWrap(true);titleLabel->setAlignment(Qt::AlignBottom);attribList=newQListWidget; //创建显示车型详细信息的列表QGridLayout*layout=newQGridLayout;layout->addWidget(profileLabel,0,0,1,2);layout->addWidget(titleLabel,1,0,1,2);layout->addWidget(attribList,2,0,1,2); //将创建的各界面元素添加进布局layout->setRowStretch(2,1);box->setLayout(layout);returnbox;}开发视图界面(4)createMenuBar()函数创建系统的操作菜单,本系统的菜单包含“添加”、“删除”和“退出”三个选项,用于后面往系统中添加和删除汽车信息以及退出系统,代码如下:voidMainWindow::createMenuBar(){QAction*addAction=newQAction("添加",this);QAction*deleteAction=newQAction("删除",this);QAction*quitAction=newQAction("退出",this);addAction->setShortcut(tr("Ctrl+A"));deleteAction->setShortcut(tr("Ctrl+D"));quitAction->setShortcut(tr("Ctrl+Q"));QMenu*fileMenu=menuBar()->addMenu("操作菜单");fileMenu->addAction(addAction);fileMenu->addAction(deleteAction);fileMenu->addSeparator();fileMenu->addAction(quitAction);}开发视图界面汽车信息管理系统的界面就开发好了,运行程序显示主界面及菜单效果如图。02连接数据库1.添加登录对话框界面类2.设计登录对话框界面3.声明获取参数及连接函数4.加载可用数据库驱动5.获取参数6.建立连接7.启动登录对话框连接数据库本系统用户是通过如图的对话框图形界面配置参数连上数据库,然后登录进系统的,下面来开发这个模块。连接数据库1.添加登录对话框界面类(1)右击项目名,选择“添加新文件...”,弹出“新建文件”向导对话框,选择模板“Qt”→“Qt设计师界面类”条目项,如图,单击“Choose...”按钮。连接数据库(2)接下来在如图的界面上,选择“DialogwithoutButtons”界面模板,单击“下一步”按钮。连接数据库(3)在“选择类名”界面上将登录对话框的类名(Classname)命名为ConnDlg,在下方的几栏分别命名与其相关的程序文件:头文件(Headerfile)名为connectdlg.h、源文件(Sourcefile)名为connectdlg.cpp、界面文件(Formfile)名为connectdlg.ui,如图,单击“下一步”按钮,最后单击“完成”按钮。连接数据库2.设计登录对话框界面登录对话框界面采用QtCreator的可视化方式进行设计。在开发环境项目树形视图中双击“Forms”节点下的界面文件connectdlg.ui,进入到QtDesigner设计环境,往设计区窗体上拖曳添加如图的控件并布局整齐。连接数据库各控件的属性见表。类名
称文
本类名
称文
本QGroupBoxconnGroupBox数据库连接设置
QLabeltextLabel2驱动:QComboBoxcomboDriver
QLabeltextLabel3数据库名:QLineEditeditDatabasecarviewQLabeltextLabel4用户名:QLineEditeditUsernamerootQLabeltextLabel4_2密码:QLineEditeditPassword123456QLabeltextLabel5主机名:QLineEditeditHostnamelocalhostQLabeltextLabel5_2端口:QSpinBoxportSpinBox3306QLabeltextLabel1状态:QLabellabelStatus
QPushButtonokButton连接QPushButtoncancelButton退出连接数据库3.声明获取参数及连接函数ConnDlg类继承自QDialog类,它的主要功能是从登录对话框界面上获取用户所设置的各项连接参数,然后以这些参数值来建立数据库连接。在ConnDlg类的头文件connectdlg.h中声明了这些获取参数及建立连接的函数,如下。4.加载可用数据库驱动(1)在项目的配置文件MyC中添加一句:QT+=sql连接数据库(2)在源文件connectdlg.cpp中,ConnDlg类的构造函数在初始化UI界面的时候查找当前Qt系统中所有可用的数据库驱动,将它们载入界面上的驱动组合框中,代码如下:#include"connectdlg.h"#include"ui_connectdlg.h"#include<QSqlDatabase>#include<QtSql>ConnDlg::ConnDlg(QWidget*parent):QDialog(parent),ui(newUi::ConnDlg){ui->setupUi(this);QStringListdrivers=QSqlDatabase::drivers(); //(a)ui->comboDriver->addItem("");ui->comboDriver->addItems(drivers); //(b)ui->comboDriver->clearEditText();ui->labelStatus->setText("准备连接..."); //(c)}连接数据库5.获取参数在源文件connectdlg.cpp中编写前面声明的用于获取参数的各个函数(driverName()、databaseName()、userName()、password()、hostName()、port()),代码如下:6.建立连接当用户设置完参数单击“连接”按钮时,系统会自动执行登录对话框的on_okButton_clicked()槽函数,编写其代码如下:voidConnDlg::on_okButton_clicked(){if(ui->comboDriver->currentText().isEmpty()) //(a){ui->labelStatus->setText("请选择一个数据库驱动!");ui->comboDriver->setFocus();}else{QSqlErrorerr=addConnection(driverName(),databaseName(),userName(),password(),hostName(),port()); //(b)if(err.type()!=QSqlError::NoError) //(c){ui->labelStatus->setText(err.text());}else{ //(d)ui->labelStatus->setText("连接成功!");accept();}}}连接数据库addConnection()函数用来建立一条数据库连接,其具体实现代码如下:QSqlErrorConnDlg::addConnection(constQString&driver,constQString&dbName,constQString&user,constQString&passwd,constQString&host,intport){QSqlErrorerr;QSqlDatabasedb=QSqlDatabase::addDatabase(driver);db.setDatabaseName(dbName);db.setHostName(host);db.setPort(port);if(!db.open(user,passwd)){err=db.lastError();}returnerr;}连接数据库7.启动登录对话框登录对话框是必须在程序运行一开始就首先启动的界面,只有成功连上了数据库才能接着访问汽车信息管理系统的主界面,否则无法进入系统。为了在一开始首先启动登录对话框,需要修改项目入口文件main.cpp的代码如下:#include"mainwindow.h"#include<QApplication>#include<QDialog>#include"connectdlg.h"intmain(intargc,char*argv[]){QApplicationa(argc,argv);ConnDlgdialog;if(dialog.exec()!=QDialog::Accepted)return-1;dialog.show();MainWindoww;w.show();returna.exec();}连接数据库启动程序,出现登录对话框,由于本例使用的后台数据库是MySQL,所以在第一栏驱动组合框中选择Qt的MySQL驱动“QMYSQL”,如图。03开发主/从视图1.创建和加载模型数据2.实现主从视图联动3.显示汽车详细信息4.关联模型/视图、信号/槽开发主/从视图首先,在头文件mainwindow.h中添加如下几部分代码。(1)包含要用的库:#include<QSqlTableModel>#include<QSqlRelationalTableModel>#include<QModelIndex>#include<QJsonObject>#include<QJsonDocument>(2)声明槽函数:privateslots:voidchangeFactory(QModelIndexindex);voidshowFactorytProfile(QModelIndexindex);voidshowCarDetails(QModelIndexindex);(3)定义模型及声明私有函数:private:QSqlTableModel*factoryModel;QSqlRelationalTableModel*carModel;voidloadModel();QModelIndexindexOfFactory(constQString&factory);开发主/从视图1.创建和加载模型数据在源文件mainwindow.cpp构造函数中添加如下代码:#include<QMessageBox>#include<QSqlRecord>MainWindow::MainWindow(QWidget*parent):QMainWindow(parent){factoryModel=newQSqlTableModel(this); //(a)carModel=newQSqlRelationalTableModel(this); //(b)loadModel(); //(c)......}开发主/从视图说明:(a)factoryModel=newQSqlTableModel(this):为汽车制造商表factory创建一个QSqlTableModel模型。(b)carModel=newQSqlRelationalTableModel(this):为汽车表cars创建一个QSqlRelationalTableModel模型。(c)loadModel():这个函数用来加载模型数据,由于同样的加载操作在程序其他地方也会用到,故封装为一个函数,此函数代码如下:voidMainWindow::loadModel(){factoryModel->setTable("factory");factoryModel-
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 快捷消费食品企业县域市场拓展与下沉战略研究报告
- 碳素电极企业县域市场拓展与下沉战略研究报告
- 运动及休闲服装百货企业县域市场拓展与下沉战略研究报告
- 蓝麦啤酒企业ESG实践与创新战略研究报告
- 硼矿企业县域市场拓展与下沉战略研究报告
- 短袖衬衫企业县域市场拓展与下沉战略研究报告
- 临时聘用劳务合同范文8篇
- 农村合作社的合同范本6篇
- 解除处分申请书1500字
- 二零二五年度商场与网络安全公司合作保障信息安全的协议
- MSA-测量系统分析模板
- 血透室公休座谈水肿的护理
- 屈原《国殇》课件
- 急诊预检分诊专家共识课件
- 广州市海珠区事业单位考试历年真题
- 2023年山西省太原市迎泽区校园招考聘用教师笔试题库含答案详解
- 2023中职27 婴幼儿保育 赛题 模块三 婴幼儿早期学习支持(赛项赛题)
- 湖北省丹江口市樊家湾矿区钛磁铁矿资源储量核实报(截至2016年12月底)
- 教师师德和专业发展课件
- 服务器巡检报告模版
- 2023年高中生物新教材人教版(2023年)必修二全册教案
评论
0/150
提交评论