2024年5月13日发(作者:)
Qter开源社区
《Qt Creator快速入门》第2版
实验讲义
2014年6月
Qter开源社区
目 录
实验1 Qt开发环境的搭建......................................................- 2 -
目的与要求..................................................................................................................- 2 -
实验准备......................................................................................................................- 2 -
实验内容......................................................................................................................- 2 -
实验2 编译和发布Qt程序...................................................- 16 -
目的与要求................................................................................................................- 16 -
实验准备....................................................................................................................- 16 -
实验内容....................................................................................................................- 16 -
实验3 使用Qt资源文件.......................................................- 25 -
目的与要求................................................................................................................- 25 -
实验准备....................................................................................................................- 25 -
实验内容....................................................................................................................- 25 -
实验4 创建登陆对话框..........................................................- 30 -
目的与要求................................................................................................................- 30 -
实验准备....................................................................................................................- 30 -
实验内容....................................................................................................................- 30 -
实验5 定时器和随机数..........................................................- 35 -
目的与要求................................................................................................................- 35 -
实验准备....................................................................................................................- 35 -
实验内容....................................................................................................................- 35 -
实验6 编译MySQL数据库驱动............................................- 38 -
目的与要求................................................................................................................- 38 -
实验准备....................................................................................................................- 38 -
实验内容....................................................................................................................- 38 -
实验7 数据库基本操作............................................................- 49 -
目的与要求................................................................................................................- 49 -
实验准备....................................................................................................................- 49 -
实验内容....................................................................................................................- 49 -
实验8 Qt数据库应用编程(综合设计)................................- 55 -
目的与要求................................................................................................................- 55 -
实验准备....................................................................................................................- 55 -
实验内容....................................................................................................................- 55 -
- 1 -
Qter开源社区
实验1 Qt开发环境的搭建
目的与要求
(1)掌握Qt开发环境的搭建方法
(2)掌握Qt Creator的基本使用方法
(3)了解Qt Creator的界面布局
(4)了解Qt相关工具软件
实验准备
(1)对Qt及Qt Creator有基本了解
(2)了解MinGW
(3)下载Qt 4.8.5、Qt Creator 2.8.0和MinGW安装包
实验内容
1.安装Qt Creator
(1)双击运行安装包,将出现如图1.1所示的安装
向导界面。单击“下一步”按钮。
图1.1 Qt Creator安装向导
(2)选择安装位置界面如图1.2所示。这里默认安装在C盘,选中“Associate common file
types with Qt Creator”选项会为Qt Creator关联相应类型的文件,以后双击相应类型的文件
(如Qt项目文件)可直接在Qt Creator中打开。这里保持默认设置,单击“下一步”按钮。
- 2 -
Qter开源社区
图1.2 选择安装位置
(3)在如图1.3所示的“许可协议”界面,选择“我接受此许可”即可。然后单击“下一
步”按钮。
图1.3 许可协议界面
(4)在设置“开始菜单快捷方式”界面,可以在系统开始菜单中创建Qt Creator的快捷方
式,可以选择显示的位置和更改显示名称。如图1.4所示。这里保持默认即可。单击“下一
步”按钮。
- 3 -
Qter开源社区
图1.4 设置开始菜单快捷方式
(5)在“已做好安装准备”界面,单击“安装”按钮开始安装。如图1.5所示。
图1.5 已做好安装准备界面
(6)完成安装。在完成安装界面,单击“完成”按钮结束安装。因为默认勾选了“Launch Qt
Creator”,所以完成安装后会自动运行Qt Creator。如图1.6所示。
- 4 -
Qter开源社区
图1.6 完成安装
(7)Qt Creator的主界面如图1.7所示。可以点击各个菜单和功能图标,对Qt Creator界面
进行初步了解。
图1.7 Qt Creator主界面
2.安装MinGW
需要将下载好的MinGW-gcc440_文件解压缩到C盘Qt目录下。解压缩完成后,
- 5 -
Qter开源社区
在C盘Qt目录下会出现mingw目录。如图1.8所示。
图1.8 解压缩后的mingw目录
3.安装Qt
(1)双击运行安装包。首先出现的是安装向导界面,如
图1.9所示。单击“Next”按钮。
图1.9 Qt安装向导界面
(2)Qt开源版本介绍界面如图1.10所示。这里说明了现在安装的Qt是开源版本,使用GNU
LGPL 2.1和GPL 3版本的开源协议。单击“Next”按钮。
- 6 -
Qter开源社区
图1.10 Qt开源版本介绍
(3)在许可协议界面,选择“I accept the terms of the License Agreement”,如图1.11所示。
然后单击“Next”按钮。
图1.11 选择许可协议
(4)在选择组件界面,保持默认设置即可,如图1.12所示。然后单击“Next”按钮。
- 7 -
Qter开源社区
图1.12 选择组件界面
(5)设置安装位置。这里使用默认的安装路径,会与前面安装的Qt Creator在同一个目录
下,即C盘的Qt目录中。如图1.13所示。单击“Next”按钮。
图1.13 设置安装路径
(6)设置开始菜单目录。这里保持默认即可,如图1.14所示。单击“Next”按钮。
- 8 -
Qter开源社区
图1.14 设置开始菜单目录
(7)设置MinGW目录。这里需要指定MinGW的安装目录,因为前面已经将其解压缩到C
盘Qt目录下,所以这里设置为相应路径即可(C:Qtmingw)。如图1.15所示。然后点击“Install”
按钮安装Qt。
图1.15 设置MinGW路径
(8)完成安装。在完成安装界面默认选中了“Run Examples and Demos”和“Show
Documentation”选项,这样会自动运行Qt演示程序与示例、Qt助手两个Qt工具。如图1.16
所示。单击“Finish”完成安装。
- 9 -
Qter开源社区
图1.16 完成安装
4.关联Qt Creator和Qt
前面安装的Qt Creator、MinGW和Qt并没有自动关联到一起,需要手动进行设置将其
关联到一起才能编译运行程序。
(1)打开Qt Creator,选择“工具→选项”菜单项,然后选择“构建和运行”项。选择“编
译器”页面,点击右上角的“添加”按钮,选择第一项MinGW,然后添加编译器路径
C:,完成后点击下面的“应用”按钮保存设置,如图1.17所示。
图1.17 设置编译器
(2)下面选择“Qt版本”页面,点击右上方的“添加”按钮,然后找到的路径
即C:,完成后再次点击“应用”按钮保存设置,如图1.18所示。
- 10 -
Qter开源社区
图1.18 设置Qt版本
(3)最后到“构建套件(Kit)”页面,可以看到已经有了一个“桌面(默认)”,这里点击它
直接进行设置。名称可以随意设置,这里修改为“Desktop Qt 4.8.5”,表明是Qt 4.8.5的桌
面版;下面编译器一项已经默认选择了前面设置的MinGW;最后将Qt版本选择为前面添
加的Qt 4.8.5(4.8.5)一项。如图1.19所示。最后点击“确定”按钮保存退出。
图1.19 设置构建套件界面
5.运行一个示例程序
(1)设定Qt库以后,在欢迎界面点击“示例”页面就可以看到所有示例程序了,它们几乎
涉及到了Qt支持的所有功能。如图1.20所示。
- 11 -
Qter开源社区
图1.20 示例程序
(2)这里还提供了一个搜索栏,可以进行示例程序的查找,比如查找所有和对话框相关的
例子,可以输入“dialog”关键字,结果如图1.21所示。
图1.21 dialog相关示例
(3)下面选择Embedded Dialogs示例程序,这时便进入了编辑模式。每当打开一个示例程
序,Qt Creator便会自动打开该程序的项目文件,然后进入编辑模式,并且打开该示例的帮
助文件。可以在项目文件列表中查看该示例的源代码。如图1.22所示。
- 12 -
Qter开源社区
图1.22 打开一个示例程序
(4)现在单击左下角的运行按钮,程序便开始编译运行,在下面的“应用程序输出”栏
会显示程序的运行信息和调试输出信息。如图1.23所示。
图1.23 程序运行效果
6.查看Qt工具
前面安装的Qt 4.8.5中包含了几个很有用的工具,分别是Qt Assistant(Qt助手)、Qt
Designer(Qt设计师)、Qt Examples and Demos(Qt演示程序与示例)和Qt Linguist(Qt语
言家)。可以从开始菜单启动它们。如图1.24所示。现在先来运行这些工具,对其有一个大
概了解。
- 13 -
Qter开源社区
图1.24 Qt工具菜单目录
(1)运行Qt Assistant(Qt助手),如图1.25所示。
图1.25 Qt Assistant
(2)运行Qt Designer(Qt设计师),如图1.26所示。
图1.26 Qt Designer
- 14 -
Qter开源社区
(3)运行Qt Examples and Demos(Qt演示程序与示例),如图1.27所示。
图1.27 Qt Examples and Demos
(4)运行Qt Linguist(Qt语言家),如图1.28所示。
图1.28 Qt Linguist
思考题:
Qt Creator、Qt和MinGW各有什么作用,它们怎样关联在一起?
- 15 -
Qter开源社区
实验2 编译和发布Qt程序
目的与要求
(1)掌握创建Qt程序的方法
(2)掌握发布Qt程序的方法
(3)学会为Qt 程序添加应用程序图标
(4)了解Qt发布需要的DLL动态库文件
实验准备
(1)搭建好Qt开发环境
(2)了解Qt Creator设计模式的基本使用方法
(3)了解DLL动态库文件的作用
(4)了解Debug版本和Release版本的区别
实验内容
1.创建hello world程序
(1)运行Qt Creator,打开“文件→新建文件或项目”菜单项(也可以直接按下Ctrl+N快
捷键),在选择模板页面选择应用程序中的“Qt Gui应用”一项,然后单击“选择”按钮,
如图2.1所示。
图2.1 选择模板
(2)输入项目信息。在“项目介绍和位置”页面输入项目的名称为helloworld,然后单击
创建路径右边的“浏览”按钮,在F盘(如果没有F盘,也可以使用其他位置)中右击鼠
标新建文件夹,命名为“2-1”,然后单击“选择文件夹”即可。如果选中了这里的“设置默
认的项目路径”,那么以后创建的项目会默认使用该目录,如图2.2所示。单击“下一步”
按钮进入下个页面。(注意:项目名和路径中都不能出现中文。)
- 16 -
Qter开源社区
图2.2项目介绍与位置
(3)选择构建套件。这里显示的Desktop Qt 4.8.5就是在实验1中添加的构建套件,下面默
认为Debug版本和Release版本分别设置了两个不同的目录,如图2.3所示。然后单击“下
一步”按钮。
图2.3 选择构建套件
(4)输入类信息。在“类信息”页面中创建一个自定义类。这里设定类名为HelloDialog,
基类选择QDialog,表明该类继承自QDialog类,使用这个类可以生成一个对话框界面。这
时下面的头文件、源文件和界面文件都会自动生成,保持默认即可,如图2.4所示。然后单
击“下一步”按钮。
- 17 -
Qter开源社区
图2.4类信息
(5)设置项目管理。在这里可以看到这个项目的汇总信息,还可以使用版本控制系统,这个
项目不会涉及,所以可以直接单击“完成”按钮完成项目的创建。如图2.5所示。
图2.5项目管理
(6)项目建立完成后会直接进入编辑模式。界面的右边是编辑器,可以阅读和编辑代码。
如果觉得字体太小,可以使用快捷键Ctrl +“+”(即同时按下Ctrl键和+号键)来放大字体,
使用Ctrl + “-”(减号)来缩小字体,也可以使用Ctrl键+鼠标滚轮来缩放字体。使用Ctrl+0
(数字)可以使字体还原到默认大小。在左边侧边栏,罗列了项目中的所有文件,如图2.6
所示。
- 18 -
Qter开源社区
图2.6编辑模式
(7)在Qt Creator的编辑模式下双击项目文件列表中界面文件分类下的文件,
这时便进入了设计模式,如图2.7所示。
图2.7 设计模式
(8)从部件列表中找到Label(标签)部件,然后按着鼠标左键将它拖到主设计区的界面上,
再双击它进入编辑状态后输入“Hello World! 你好Qt!”字符串。如图2.8所示。
- 19 -
Qter开源社区
图2.8 添加标签部件
2.运行并发布程序
(1)可以使用快捷键Ctrl+R或者通过按下左下角的运行按钮来运行程序。这时可能会弹出
“保存修改”对话框,这是因为刚才在设计模式更改了界面,而文件被修改了
但是还没有保存。现在要编译运行该程序,就要先保存所有文件。可以选中“构建之前总是
先保存文件”选项,以后再运行程序时就可以自动保存文件了。然后单击“保存所有”按钮,
如图2.9所示。
图2.9保存修改对话框
(2)程序运行效果如图2.10所示。
图2.10 Helloworld程序运行效果
- 20 -
Qter开源社区
(4)要发布程序时,要使用release版本。在Qt Creator中对helloworld程序进行release版
本的编译,需要在左下角的目标选择器(Target selector)中将构建目标设置为Release,如
图2.11所示,然后单击运行图标编译运行程序。
图2.11 目标选择器
(5)编译完成之后查看项目目录中build-helloworld-Desktop_Qt_4_8_5-Release文件夹的
release目录中,已经生成了文件。如图2.12所示。
图2.12 生成的helloworld可执行程序
(6)在桌面上新建一个文件夹,重命名为“我的第一个Qt程序”,然后将release文件夹中
的复制过来,再去Qt安装目录的bin目录(C:Qt4.8.5bin)中将、
libgcc_s_、和这4个文件(注意不是和
,它们是debug版本的库文件)复制过来。这时已经可以直接运
行了。如图2.13所示。
- 21 -
Qter开源社区
图2.13 第一个应用程序
3.设置应用程序图标
在程序发布时,一般会给可执行文件设置一个漂亮的图标。下面是在Windows系统上
设置应用程序图标的方法。
(1)创建.ico文件。将ico图标文件复制到工程文件夹的helloworld目录中,重命名为
“”。然后在该目录中右击,新建文本文档,并输入一行代码:
IDI_ICON1 ICON DISCARDABLE ""
如图2.14所示。
图2.14 新建文本文件
(2)选择“文件→另存为”菜单项,将该文件命名为(注意文件后缀为.rc),然后
单击“保存”。完成后可以将以前的“新建文本文档”删除。最后helloworld文件夹中的内
容如图2.15所示。
- 22 -
Qter开源社区
图2.15 创建文件
(3)修改项目文件。在Qt Creator中的编辑模式双击文件,在最后面添加下
面一行代码:
RC_FILE +=
如图2.16所示。
图2.16 修改项目文件
(4)运行程序。可以看到窗口的左上角的图标已经更换了,如图2.17所示。
图2.17 更换了图标的程序运行界面
- 23 -
Qter开源社区
(5)查看一下release文件夹中的文件,可以看到现在exe文件已经更换了新的图标,如图
2.18所示。
图2.18更换了图标后的release目录
(6)现在可以将更改了图标的文件复制到程序发布目录,然后就可以将程序
发布目录压缩打包进行发布了。发布的程序可以在没有安装Qt的Windows系统上运行。
思考题:
Qt程序从编写、编译、运行,到最后的发布,整个流程是怎样的?
- 24 -
Qter开源社区
实验3 使用Qt资源文件
目的与要求
(1)掌握设置菜单栏方法
(2)掌握使用Qt资源文件的方法
(3)会使用代码添加菜单
(4)了解资源文件的构成
实验准备
(1)搭建好Qt开发环境
(2)了解使用Qt Creator创建Qt应用程序的流程
(3)了解应用程序主窗口的组成
(4)准备好需要使用的图标文件
实验内容
1.创建主窗口菜单
(1)新建Qt Gui应用,项目名称为myMainWindow,基类选择QMainWindow,类名为
MainWindow。
(2)创建完项目后,双击文件进入设计模式。可以看到界面左上角的“在
这里输入”,可以在这里添加菜单。双击“在这里输入”,将其更改为“文件(&F)”,然后按
下回车键,效果如图3.1所示。这里的&F表明将菜单的快捷键设置为了Alt + F,可以看到,
实际的显示效果中&符号是隐藏的。
图3.1 创建菜单
- 25 -
Qter开源社区
(3)同样的方法,在文件菜单中添加“新建(&N)”菜单项,效果如图3.2所示。菜单后面
的那个加号图标是用来创建下一级菜单的。
图3.2 创建菜单项
2.添加菜单图标
(1)Qt中的一个菜单项被看做是一个Action,在设计器下面的Action编辑器中可以看到刚
才添加的“新建”动作,如图3.3所示。
图3.3 动作编辑器
(2)双击action_N条目,会弹出编辑动作对话框,这里可以进行各项设置,比如可以设置
动作的快捷键,点击一下快捷键后面的行编辑器,然后按下键盘上的Ctrl + N,这样就可以
将该菜单的快捷键设置为Ctrl + N。如图3.4所示。
图3.4 编辑动作
(3)在编辑动作对话框中的图标后面的黑色箭头下拉框可以选择使用资源还是使用
文件,如果使用文件的话,那么就可以直接在弹出的文件对话框中选择本地磁盘上的一个图
标文件。如果直接点击这个按钮就是默认的使用资源。现在先按下编辑动作对话框的“确定”
按钮关闭它。
- 26 -
Qter开源社区
3.添加资源文件
Qt中可以使用资源文件将各种类型的文件添加到最终生成的可执行文件中,这样就可
以避免使用外部文件可能出现的一些问题。而且,在编译时Qt还会将资源文件进行压缩,
可以使可执行文件的体积尽可能缩小。
(1)向项目中添加新文件,模板选择Qt资源文件。如图3.5所示。然后将名称设置为
“myResources”。
图3.5 创建资源文件
(2)创建完文件后会自动打开该资源文件,这里需要先在下面添加前缀,点击添加按钮,
然后选择前缀,默认的前缀是“/new/prefix1”,这个可以随意修改(不要出现中文字符)。
这里因为要添加图片,所以修改为/myImages。然后再按下添加按钮来添加文件,这里最好
将所有要用到的图片放到项目目录中。比如这里在项目目录中新建了一个images文件夹,
然后将需要的图标文件复制粘贴进去。添加完文件后,如图3.6所示。
图3.6 添加图片
(3)当添加完资源后,一定要按下Ctrl + S来保存资源文件,不然在后面可能无法显示已
- 27 -
Qter开源社区
经添加的资源。
4.使用资源文件
(1)重新到设计模式打开新建菜单的编辑动作对话框,然后添加图标。在打开的选择资源
对话框中,第一次可能无法显示已经存在的资源,可以按下左上角的绿箭头
效果如图3.7所示。
来更新显示。
图3.7 添加资源图标
(2)点击这里需要的新建图标,按下“确定”按钮即可。现在按下Ctrl + R键
运行程序,效果如图3.8所示。
图3.8 添加图标运行效果
5.使用代码来添加菜单和图标
(1)对于添加的资源文件,在项目目录中可以看到,即,使用写字板程序
- 28 -
Qter开源社区
将其打开,可以发现它其实就是一个XML文档:
(2)前面是在设计模式添加的图标文件,下面使用代码再来添加一个菜单,并为其设置图
标。在编辑模式打开文件,并在构造函数中添加如下代码:
// 创建新的动作
QAction *openAction = new QAction(tr("&Open"), this);
// 添加图标
QIcon icon(":/myImages/images/");
openAction->setIcon(icon);
// 设置快捷键
openAction->setShortcut(QKeySequence(tr("Ctrl+O")));
// 在文件菜单中设置新的打开动作
ui->menu_F->addAction(openAction);
这里添加图标时,就是使用的资源文件中的图标。使用资源文件,需要在最开始使用冒
号,然后添加前缀,后面是文件的路径。在代码中使用文件菜单,就是使用其objectName
属性。
(3)现在运行程序查看效果。
思考题:
使用资源文件和直接使用本地的图片文件,这两种方式有什么优缺点?
- 29 -
Qter开源社区
实验4 创建登陆对话框
目的与要求
(1)掌握自定义部件类的方法
(2)学会使用信号和槽机制
(3)了解如何创建登录对话框
(4)了解密码显示的方式
实验准备
(1)搭建好Qt开发环境
(2)会使用Qt设计模式设计界面
(3)了解信号和槽的基本概念
实验内容
编写程序,实现在程序主界面出现以前,弹出登录对话框,并可以填写用户名和密码,
当按下登录按钮,如果用户名和密码均正确则进入主窗口,如果有错则弹出警告对话框。
1.创建程序
(1)新建Qt Gui应用,项目名称为“login”,类名和基类保持MainWindow和QMainWindow
不变。
(2)完成项目创建后,向项目中添加新的Qt设计师界面类,模板选择Dialog without Buttons,
类名更改为“LoginDialog”。完成后向界面上添加两个标签Label、两个行编辑器Line Edit
和两个按钮Push Button,设计界面如图4.1所示。
图4.1 设计界面效果
(3)在属性编辑器中将用户名后面的行编辑器的object Name属性更改为“usrLineEdit”,
- 30 -
Qter开源社区
密码后面的行编辑器的object Name属性更改为“pwdLineEdit”,登录按钮的object Name属
性更改为“loginBtn”,退出按钮的object Name属性更改为“exitBtn”。如图4.2所示。
图4.2 修改对象名称属性
(4)在设计模式下面的信号和槽编辑器中,先点击左上角的绿色加号添加关联,然后选择
发送者为exitBtn,信号为clicked(),接收者为LoginDialog,槽为close()。如图4.3所示。
这样,当单击退出按钮时,就会关闭登录对话框。
图4.3 添加信号和槽关联
(5)右击登录按钮,在弹出的菜单中选择“转到槽…”,然后选择clicked()信号并确定。转
到相应的槽以后,添加函数调用:
void LoginDialog::on_loginBtn_clicked()
{
accept();
}
(6)下面到文件,更改内容如下:
#include
#include "mainwindow.h"
#include "logindialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
LoginDialog dlg;
if (() == QDialog::Accepted)
{
();
return ();
}
- 31 -
Qter开源社区
else return 0;
}
(7)运行程序,按下退出按钮会退出程序,按下登录按钮会关闭登录对话框,
并显示主窗口。
2.登录设置
(1)下面添加代码来实现使用用户名和密码登录,这里只是简单的将用户名和密码设置为
了固定的字符串。到文件中将登录按钮的单击信号对应的槽更改如下:
void LoginDialog::on_loginBtn_clicked()
{
// 判断用户名和密码是否正确,
// 如果错误则弹出警告对话框
if(ui->usrLineEdit->text() == tr("yafeilinux") &&
ui->pwdLineEdit->text() == tr("123456"))
{
accept();
} else {
QMessageBox::warning(this, tr("Waring"),
tr("user name or password error!"),
QMessageBox::Yes);
}
}
Qt中的QMessageBox类提供了多种常用的对话框类型,比如这里的警告对话框,还有
提示对话框,问题对话框等。这里使用了静态函数来设置了一个警告对话框,这种方式很方
便。其中的参数依次是:this表明父窗口是登录对话框;然后是窗口标题;然后是显示的内
容;最后一个参数是显示的按钮,这里使用了一个Yes按钮。
在添加QMessageBox类的头文件包含,即:
#include
(2)运行程序,如果输入用户名为“yafeilinux”,密码为“123456”,那么可以登录,如果
输入其他的字符,则会弹出警告对话框,如图4.4所示。
图4.4 运行效果
- 32 -
Qter开源社区
(3)对于输入的密码,常见的是显示成小黑点的样式。下面点击文件进入设
计模式,然后选中界面上的密码行编辑器部件,在其属性编辑器中将echoMode属性选择为
Password。这时再次运行程序,可以看到密码显示已经改变显示样式了。如图4.5所示。
图4.5 修改密码显示效果
除了在属性编辑器中进行更改,也可以在loginDialog类的构造函数中使用
setEchoMode(QLineEdit::Password)函数来设置。
(4)在行编辑器的属性栏中还可以设置占位符,就是没有输入信息前的一些提示语句。例
如将密码行编辑器的placeholderText属性更改为“请输入密码”,将用户名行编辑器的更改
为“请输入用户名”,运行效果如图4.6所示。
图4.6 占位符运行效果
(5)对于行编辑器,还有一个问题就是,比如输入用户名,不小心在前面添加了一个空格,
这时也需要保证输入是正确的,这个可以使用QString类的trimmed()函数来实现,它可以去
除字符串前后的空白字符。下面将文件中登录按钮单击信号关联的槽函数中
的判断代码更改为:
if(ui->usrLineEdit->text().trimmed() == tr("yafeilinux")
&& ui->pwdLineEdit->text() == tr("123456"))
- 33 -
Qter开源社区
这时运行程序,就可以实现相应的功能了。
(6)当登录失败后,希望可以清空用户名和密码信息,并将光标定位到用户名输入框中。
这个可以通过在判断用户名和密码错误后添加相应的代码来实现:
void LoginDialog::on_loginBtn_clicked()
{
// 判断用户名和密码是否正确,如果错误则弹出警告对话框
if(ui->usrLineEdit->text().trimmed() == tr("yafeilinux")
&& ui->pwdLineEdit->text() == tr("123456"))
{
accept();
} else {
QMessageBox::warning(this, tr("Waring"),
tr("user name or password error!"),
QMessageBox::Yes);
// 清空内容并定位光标
ui->usrLineEdit->clear();
ui->pwdLineEdit->clear();
ui->usrLineEdit->setFocus();
}
}
下面运行程序并测试效果。
思考题:
还有没有其他方式来实现登录窗口?
- 34 -
Qter开源社区
实验5 定时器和随机数
目的与要求
(1)掌握使用定时器的方法
(2)掌握随机数的设置方法
(3)会使用定时器实现时钟
(4)了解图片显示的方法
实验准备
(1)了解信号和槽的基本使用方法
(2)了解定时器和随机数的基本概念
(3)准备好需要使用的图片文件
实验内容
使用定时器可以在指定时间执行一些功能,而要实现随机效果就要使用随机数来实现。
新建程序实现电子时钟效果,并每隔一秒就可以随机显示一张图片。
(1)新建Qt Gui应用,项目名称为myTimer,基类选择QWidget,类名为Widget。
(2)完成项目创建后,双击进入设计模式,然后向界面上拖入两个Push Button、
一个Line Edit和一个Label部件,修改其显示文本,效果如图5.1所示。
图5.1 设计界面效果
(3)然后到widget.h文件中添加类的前置声明:
class QTimer;
再添加一个私有槽声明:
private slots:
- 35 -
Qter开源社区
void timerUpdate();
和一个私有对象定义:
private:
QTimer *timer;
(4)到中,先添加头文件包含:
#include
#include
然后在构造函数中添加如下代码:
timer = new QTimer(this);
//关联定时器溢出信号和相应的槽函数
connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate()));
qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
这里创建了一个定时器,并将其溢出信号和更新槽关联起来,最后使用start()函数来
开启定时器。
关于随机数,在Qt中是使用qrand()和qsrand()两个函数实现的。qrand()函数可以产
生随机数,qrand()%10可以产生0-9之间的随机数。要想产生100以内的随机数就是%100。
以此类推。在使用qrand()函数产生随机数之前,一般要使用qsrand()函数为其设置初值,
如果不设置初值,那么每次运行程序,qrand()都会产生相同的一组随机数。为了每次运行
程序时,都可以产生不同的随机数,要使用qsrand()设置一个不同的初值。这里使用了QTime
类的secsTo()函数,它表示两个时间点之间所包含的秒数,比如代码中就是指从零点整到
当前时间所经过的秒数。
(5)下面在文件中添加timerUpdate()函数的定义:
void Widget::timerUpdate()
{
//获取系统现在的时间
QDateTime time = QDateTime::currentDateTime();
//设置系统时间显示格式
QString str = ng("yyyy-MM-dd hh:mm:ss dddd");
//在标签上显示时间
ui->lineEdit->setText(str);
int rand = qrand() % 5; // 产生5以内随机整数:0-4
ui->label->setPixmap(QString("../myTimer/images/%").arg(rand));
}
这里在行编辑器中显示了当前的时间。然后使用qrand() % 产生5以内的随机数,并
使用这个随机数来获取图片名称。
(6)前面代码中使用了、、、、这样5张图片,需要复制5
张图片到项目目录下面新建的images目录中。
(7)在设计模式,分别右击“开始”按钮和“停止”按钮,选择转到槽,然后选择clicked()
信号。将对应的槽函数修改如下:
// 开始按钮
void Widget::on_pushButton_clicked()
{
- 36 -
Qter开源社区
timer->start(1000);
}
// 停止按钮
void Widget::on_pushButton_2_clicked()
{
timer->stop();
}
(8)运行程序,点击“开始”按钮,会显示当前系统时间,并每隔一秒随机显示一张图片。
效果如图5.2所示。
图5.2 程序运行效果
思考题:
怎样利用随机数使程序出现随机效果?
- 37 -
Qter开源社区
实验6 编译MySQL数据库驱动
目的与要求
(1)掌握数据库驱动的编译方法
(2)掌握MySQL数据库的简单操作命令
(3)掌握在Qt程序中关联MySQL数据库的方法
(4)了解Qt默认支持的数据库类型
实验准备
(1)对MySQL数据库初步了解
(2)了解编译数据库驱动的基本过程
(3)了解Qt操作数据库的基本方法
实验内容
1.安装MySQL
(1)从/?page_id=161下载MySQL安装包mysql-5.6.10-win32,如图6.1
所示。
图6.1 下载文件
(2)运行下载的安装包,首先出现的是向导欢迎界面。如图6.2所示。单击“Next”按钮。
图6.2 欢迎界面
- 38 -
Qter开源社区
(3)该界面选择同意条款。如图6.3所示。单击“Next”按钮。
图6.3 服务条款界面
(4)下面选择定制安装“Custom”。如图6.4所示。
图6.4 选择定制安装
(5)这里需要安装所有的头文件和库,点击Development Components前面的下拉箭头,然后
选择第二项。如图6.5所示。
- 39 -
Qter开源社区
图6.5 选择安装的文件
(6)然后选择下面的“Browse…”按钮来更改安装路径,这里设置为C:MySQL,如图6.6
所示。
图6.6 设置安装位置
(7)填写完路径后单击“OK”按钮回到主页面,单击“Next”按钮来到新的页面,这里单
击“Install”按钮开始安装。如图6.7所示。
- 40 -
Qter开源社区
图6.7 开始安装
(8)等安装完毕后,点击“Finish”按钮完成安装。如图6.8所示。
图6.8 完成安装
2.在MySQL中创建数据库
(1)下面先在安装的MySQL中创建一个数据库,用于后面的测试。首先到MyQSL的安
装目录C:MySQLbin目录下运行程序,该程序运行完成后会自动关闭。如图6.9
所示。
- 41 -
Qter开源社区
图6.9 运行mysqld程序
(2)按下键盘上的Win图标和R键,在弹出的对话框中输入cmd。如图6.10所示。
图6.10 运行cmd
(3)进入终端后输入下面的命令:
cd C:MySQLbin
跳转到安装目录下。如图6.11所示。
图6.11 跳转目录
- 42 -
Qter开源社区
(4)然后输入下面的命令:
mysql –uroot –p
使用root用户来登陆MySQL,因为默认密码是空的,所以这里不用设置密码。运行这
行代码会提示Enter password,这时敲回车即可。如图6.12所示。
图6.12 登录MySQL
(5)登录MySQL以后,使用下面的命令来查看现有的数据库:
show databases;
注意后面有个分号。如图6.13所示。
图6.13 显示数据库
(6)可以看到,这里现在已经有几个数据库了,它们是MySQL需要的。如图6.14所示。
图6.14 已有的数据库
- 43 -
Qter开源社区
(7)这里不使用已经有的数据库,而是新建自己的数据库,下面新建名为mydata的数据库:
create database mydata;
如图6.15所示。
图6.15 创建数据库
(8)再次查看已经存在的数据库,发现显示出了刚才创建的数据库,如图6.16所示。
图6.16 再次查看数据库
(9)完成后,输入exit命令退出MySQL。
3.编译MySQL驱动
(1)进入Qt安装目录的mysql源码目录中,路径为C:Qt4.8.5srcpluginssqldriversmysql,
如图6.17所示。
图6.17 文件目录
- 44 -
Qter开源社区
(2)使用Qt Creator打开里面的项目文件。出现配置项目界面,选择“配置项目”
按钮即可。如图6.18所示。
图6.18 配置项目
(3)然后打开文件,在最下面添加下面两行代码:
INCLUDEPATH += C:/MySQL/include/
LIBS+= -LC:/MySQL/lib/ -llibmysql
这样便包含了MySQL的库和头文件。如图6.19所示。
图6.19 修改项目文件
(4)现在使用左下角的锤子
按钮来构建项目。为了生成release库,在Qt Creator中运行
按钮那里设置为编译Release版本。如图6.20所示。
- 45 -
Qter开源社区
图6.20 设置为编译Release版本
(5)完成后在C:Qt4.8.5srcpluginssqldrivers会生成build-mysql-Desktop_Qt_4_8_5-Release
构建目录,里面的release目录中包含了发布release版本程序需要的dll文件。
(6)将生成的,libqsqlmysql4.a复制到C:Qt4.8.5pluginssqldrivers目录下,
这是数据库驱动插件放置的目录。如图6.21所示。
图6.21 复制生成的文件
4.测试MySQL程序
(1)打开Qt Creator,新建项目,模板选择为“Qt控制台应用”,项目名称为“sqldrivers”。
完成后在文件中添加如下代码:
QT += sql
然后按下Ctrl+S保存该文件。
(2)更改文件内容如下。
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
- 46 -
Qter开源社区
// 输出可用数据库
qDebug() << "Available drivers:";
QStringList drivers = QSqlDatabase::drivers();
foreach(QString driver, drivers)
qDebug() << driver;
// 打开MySQL
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
tName("localhost");
abaseName("mydata");
rName("root");
sword("");
if (!())
qDebug() << "Failed to connect to root mysql admin";
else qDebug() << "open";
QSqlQuery query(db);
//注意这里varchar一定要指定长度,不然会出错
("create table student(id int primary key,name varchar(20))");
("insert into student values(1,'xiaogang')");
("insert into student values(2,'xiaoming')");
("insert into student values(3,'xiaohong')");
("select id,name from student where id >= 2");
while(())
{
int value0 = (0).toInt();
QString value1 = (1).toString();
qDebug() << value0 << value1 ;
}
return ();
}
这里注意,创建表时varchar一定要指定长度。
(3)到C:MySQLlib中将文件复制到C:Qt4.8.5bin中,然后设置编译Release
版本的程序。运行程序,结果如图6.22所示。
- 47 -
Qter开源社区
思考题:
图6.22 程序运行结果
编译MySQL数据库驱动要注意哪些事项?
- 48 -
Qter开源社区
实验7 数据库基本操作
目的与要求
(1)掌握操作数据库表格的基本方法
(2)掌握使用Qt操作MySQL数据库的常用操作
(3)掌握在MySQL中使用中文的方法
(4)了解Qt调用外部程序的基本方法
实验准备
(1)编译完成MySQL数据库驱动
(2)会使用Qt创建MySQL数据库表
(3)了解QSqlTableModel的基本操作
实验内容
(1)新建Qt Gui应用,项目名称为sqlModel,类名为MainWindow,基类选择QMainWindow。
(2)完成后在文件中添加如下代码:
QT += sql
然后按下Ctrl+S保存该文件。
(3)往项目中添加新的C++头文件,名称为“connection.h”,完成后在其中添加数据库连
接函数的定义:
#ifndef CONNECTION_H
#define CONNECTION_H
#include
#include
#include
static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
tName("localhost");
abaseName("mydata");
rName("root");
sword("");
if (!()) {
QMessageBox::critical(0, QObject::tr("无法打开数据库"),
"无法创建数据库连接!", QMessageBox::Cancel);
- 49 -
Qter开源社区
return false;
}
// 下面来创建表
// 如果MySQL数据库中已经存在同名的表,那么下面的代码不会执行
QSqlQuery query(db);
// 使数据库支持中文
("SET NAMES 'Latin1'");
// 创建course表
(QString("create table course (id int primary key, "
"name varchar(20), teacher varchar(20))"));
(QString("insert into course values(0, '数学', '刘老师')"));
(QString("insert into course values(1, '英语', '张老师')"));
(QString("insert into course values(2, '计算机', '白老师')"));
return true;
}
#endif // CONNECTION_H
(4)打开文件,修改内容如下:
#include
#include "mainwindow.h"
#include "connection.h"
#include
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 这行代码要写在创建连接之前
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
// 这里使用代码来运行MySQL数据库
QProcess process;
("C:/MySQL/bin/");
if (!createConnection()) return 1;
MainWindow w;
();
- 50 -
Qter开源社区
return ();
}
(5)双击文件进入设计模式,向界面上拖入Label、Push Button、Line Edit
和Table View等部件,最终效果如图7.1所示。
图7.1 设计界面效果
(6)打开mainwindow.h文件,添加类的前置声明:
class QSqlTableModel;
然后再定义一个私有对象:
private:
QSqlTableModel *model;
(7)下面到文件中,添加头文件包含:
#include
#include
#include
#include
在构造函数中添加如下代码:
model = new QSqlTableModel(this);
model->setTable("course");
model->select();
// 设置编辑策略
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
ui->tableView->setModel(model);
(8)下面到设计模式,分别右击各个按钮,选择“转到槽”,然后选择clicked()信号。更改
各个槽函数的内容如下:
// 提交修改按钮
void MainWindow::on_pushButton_clicked()
- 51 -
Qter开源社区
{
// 开始事务操作
model->database().transaction();
if (model->submitAll()) {
model->database().commit(); //提交
} else {
model->database().rollback(); //回滚
QMessageBox::warning(this, tr("tableModel"),
tr("数据库错误: %1").arg(model->lastError().text()));
}
}
// 撤销修改按钮
void MainWindow::on_pushButton_2_clicked()
{
model->revertAll();
}
// 查询按钮,进行筛选
void MainWindow::on_pushButton_7_clicked()
{
QString name = ui->lineEdit->text();
//根据姓名进行筛选,一定要使用单引号
model->setFilter(QString("teacher = '%1'").arg(name));
model->select();
}
// 显示全表按钮
void MainWindow::on_pushButton_8_clicked()
{
model->setTable("course");
model->select();
}
// 按id升序排列按钮
void MainWindow::on_pushButton_5_clicked()
{
//id属性,即第0列,升序排列
model->setSort(0, Qt::AscendingOrder);
model->select();
}
// 按id降序排列按钮
void MainWindow::on_pushButton_6_clicked()
- 52 -
Qter开源社区
{
model->setSort(0, Qt::DescendingOrder);
model->select();
}
// 删除选中行按钮
void MainWindow::on_pushButton_4_clicked()
{
// 获取选中的行
int curRow = ui->tableView->currentIndex().row();
// 删除该行
model->removeRow(curRow);
int ok = QMessageBox::warning(this,tr("删除当前行!"),
tr("你确定删除当前行吗?"),QMessageBox::Yes, QMessageBox::No);
if(ok == QMessageBox::No)
{ // 如果不删除,则撤销
model->revertAll();
} else { // 否则提交,在数据库中删除该行
model->submitAll();
}
}
// 添加记录按钮
void MainWindow::on_pushButton_3_clicked()
{
// 获得表的行数
int rowNum = model->rowCount();
// 添加一行
model->insertRow(rowNum);
model->setData(model->index(rowNum,0),rowNum);
}
(9)选择编译运行Release版本程序(因为在实验6中可能只编译了Release版本的MySQL
驱动)。效果如图7.2所示。然后修改“刘老师”为“陈老师”,并单击“提交修改”按钮,
如图7.3所示。然后将“张老师”修改为“李老师”并按下回车键,虽然这里已经修改了,
但是并没有实际写入到数据库,单击“撤销修改”按钮,可以看到又改为了“张老师”。单
击“添加记录”按钮,会在最下面添加一行,前面的星号表示该数据还没有写入到数据库,
这里id默认为已有的最大id值加1,如图7.4所示。现在添加name为“语文”,teacher为
“周老师”,然后单击“提交修改”按钮,效果如图7.5所示。下面单击新添加的行,然后
单击“删除选中行”,就可以删除该行。在“姓名”中输入“白老师”,然后单击“查询”按
钮,就可以显示“白老师”一行,效果如图7.6所示。单击“显示全表”按钮可以再次显示
所有内容。单击“按id降序排列”按钮,可以按照id从大到小排列各行,效果如图7.7所
示。
- 53 -
Qter开源社区
图7.2 程序运行效果 图7.3 提交修改
图7.4 添加记录 图7.5 提交添加的记录
图7.6 查询效果 图7.7 排序效果
思考题:
使用其他数据库重写编写该程序,思考 Qt操作数据库与数据库类型有关吗?
- 54 -
Qter开源社区
实验8 Qt数据库应用编程(综合设计)
目的与要求
(1)掌握创建综合应用程序的方法
(2)掌握设计数据库程序的方法
(3)掌握综合程序的布局方法
(4)了解模块化编写应用程序的方法
实验准备
(1)编译完成MySQL数据库驱动
(2)会使用Qt创建MySQL数据库表
(3)了解应用程序界面布局的方法
(4)会使用常用的Qt部件
实验内容
实验的目标
该实验的目标是实现一个数据管理系统,使用密码登陆系统后,通过对数据库的操作实
现商品的出售、进货、查询等功能。实验中使用了电视和空调两种类型的商品作为例子来进
行演示,一共创建了两张数据库表:一张类型表和一张品牌表。类型表中存放所有家电的类
型,这里以电视和空调为例;在品牌表中保存了所有品牌所属的家电类型、总量、销售量和
库存量等数据。
实验步骤
1.创建程序
(1)新建Qt Gui应用,项目名称为“manager”,基类选择为QWidget,类名保持“Widget”
不变。
(2)完成后进入设计模式,将主界面的宽度和高度分别设置为750和500,windowTitle属
性设置为“数据管理系统”。然后向界面中拖入五个Push Button,调整它们的大小,并分别
更改其显示文本为“出售商品”、“商品入库”、“添加商品”、“商品查询”和“修改密码”。
然后可以将它们放入一个水平布局管理器中。下面向界面上拖入一个Stacked Widget,将其
宽度和高度分别修改为700和410,然后将currentPageName属性修改为“sellPage”。向Stacked
Widget的当前页面即sellPage中拖入一个Label部件,将Label的显示文本更改为“出售商
品”,将其font属性的点大小设置为12,将frameShape属性选择为StyledPanel,将alignment
属性中“水平的”选择为AlignHCenter。然后再向界面上添加Label、Combo Box、Line Edit、
Spin Box和Push Button等部件,最终的效果如图8.1所示。
- 55 -
Qter开源社区
图8.1 出售商品界面
(3)下面来更改部分部件的objectName属性,如表8.1所示。
表8.1 出售商品页面部件的objectName属性
部件
“出售商品”Push Button
“商品入库”Push Button
“添加商品”Push Button
“商品查询”Push Button
“修改密码”Push Button
“类型:”后面的Combo Box
“品牌:”后面的Combo Box
“单价:”后面的Line Edit
“数量:”后面的Spin Box
“剩余数量:000”Label
“金额:”后面的Line Edit
“确定”Push Button
“取消”Push Button
sellBtn
buyBtn
addBtn
queryBtn
passwordBtn
sellTypeComboBox
sellBrandComboBox
sellPriceLineEdit
sellNumSpinBox
sellLastNumLabel
sellSumLineEdit
sellOkBtn
sellCancelBtn
objectName属性
(4)下面在Stacked Widget上右击,选择“插入页→在当前页之后”来插入新的页面。在新的
页面再次拖入部件,设计效果如图8.2所示。部分部件的objectName属性如表8.2所示。
- 56 -
Qter开源社区
图8.2 商品入库界面
表8.2商品入库页面部件的objectName属性
部件
“类型:”后面的Combo Box
“品牌:”后面的Combo Box
“单价:”后面的Line Edit
“数量:”后面的Spin Box
“金额:”后面的Line Edit
“确定”Push Button
“取消”Push Button
objectName属性
goodsTypeComboBox
goodsBrandComboBox
goodsPriceLineEdit
goodsNumSpinBox
goodsSumLineEdit
goodsOkBtn
goodsCancelBtn
(5)再次插入新的页面,效果如图8.3所示。部分部件的objectName属性如表8.3所示。
图8.3 添加商品界面
- 57 -
Qter开源社区
表8.3添加商品页面部件的objectName属性
部件
“类型:”后面的Combo Box
“品牌:”后面的line Edit
“单价:”后面的Spin Box
“数量:”后面的Spin Box
“金额:”后面的Line Edit
“确定”Push Button
“取消”Push Button
objectName属性
newTypeComboBox
newBrandLineEdit
newPriceSpinBox
newNumSpinBox
newSumLineEdit
newOkBtn
newCancelBtn
(6)再次插入新的页面,拖入Label、Combo Box、Push Button和Table View等部件,效
果如图8.4所示。部分部件的objectName属性如表8.4所示。
图8.4 商品查询界面
表8.4 商品查询页面部件的objectName属性
部件
“类型:”后面的Combo Box
“品牌:”后面的Combo Box
“查询”Push Button
objectName属性
queryTypeComboBox
queryBrandComboBox
queryPushButton
(7)再次插入新的页面,效果如图8.5所示。部分部件的objectName属性如表8.5所示。
- 58 -
Qter开源社区
图8.5 修改密码界面
表8.5 商品查询页面部件的objectName属性
部件
“原密码”后面的Line Edit
“新密码”后面的Line Edit
“确定”Push Button
oldPwdLineEdit
newPwdLineEdit
changePwdBtn
objectName属性
2.连接数据库
(1)在项目文件中添加如下代码:
QT += sql
(2)往项目中添加新的C++头文件connection.h,完成后将其内容更改如下:
#ifndef CONNECTION_H
#define CONNECTION_H
#include
#include
#include
static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
tName("localhost");
abaseName("mydata");
rName("root");
sword("");
if (!()) {
- 59 -
Qter开源社区
QMessageBox::critical(0, QObject::tr("无法打开数据库"),
"无法创建数据库连接!", QMessageBox::Cancel);
return false;
}
QSqlQuery query;
// 使数据库支持中文
("SET NAMES 'Latin1'");
// 创建分类表
("create table type(id varchar(20) primary key, name varchar(20))");
(QString("insert into type values('0', '请选择类型')"));
(QString("insert into type values('01', '电视')"));
(QString("insert into type values('02', '空调')"));
// 创建品牌表
("create table brand(id varchar(20) primary key, name varchar(30), "
"type varchar(20), price int, sum int, sell int, last int)");
(QString("insert into brand values('01', '海信', '电视', 3699, 50, 10, 40)"));
(QString("insert into brand values('02', '创维', '电视', 3499, 20, 5, 15)"));
(QString("insert into brand values('03', '海尔', '电视', 4199, 80, 40, 40)"));
(QString("insert into brand values('04', '王牌', '电视', 3999, 40, 10, 30)"));
(QString("insert into brand values('05', '海尔', '空调', 2899, 60, 10, 50)"));
(QString("insert into brand values('06', '格力', '空调', 2799, 70, 20, 50)"));
// 创建密码表
("create table password(pwd varchar(50) primary key)");
("insert into password values('123456')");
return true;
}
#endif // CONNECTION_H
(3)下面进入文件,修改如下:
#include
#include "widget.h"
#include
#include "connection.h"
#include "logindialog.h"
#include
int main(int argc, char *argv[])
{
- 60 -
Qter开源社区
QApplication a(argc, argv);
// 必须在创建数据库之前使用,不然无法在数据库中使用中文
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
// 这里使用代码来运行MySQL数据库
QProcess process;
("C:/MySQL/bin/");
if(!createConnection()) return 0;
Widget w;
LoginDialog dlg;
if (() == QDialog::Accepted) {
();
return ();
} else {
return 0;
}
}
这里使用了LoginDialog类,这个是登陆窗口类,下面来创建这个类。
3.添加登陆窗口类
(1)向项目中添加新的Qt设计师界面类,模板选择Dialog without Buttons,类名设置为
“LoginDialog”。完成后往界面上拖入Push Button、Line Edit和Label等部件,最终效果如
图8.6所示。将Line Edit的objectName属性更改为“pwdLineEdit”,然后将echoMode选择
为Password;将“登录”按钮的objectName属性设置为“loginBtn”,“退出”按钮的objectName
属性设置为“quitBtn”。
图8.6 登陆窗口界面
(2)下面进入文件中,先添加头文件包含:
- 61 -
Qter开源社区
#include
#include
然后在构造函数中添加如下代码:
setFixedSize(700, 400);
setWindowTitle(tr("登录"));
ui->pwdLineEdit->setFocus();
ui->loginBtn->setDefault(true);
下面从设计模式分别进入“登录”按钮和“退出”按钮的单击信号对应的槽,更改如下:
void LoginDialog::on_loginBtn_clicked()
{
if (ui->pwdLineEdit->text().isEmpty()) {
QMessageBox::information(this, tr("请输入密码"),
tr("请先输入密码再登录!"), QMessageBox::Ok);
ui->pwdLineEdit->setFocus();
} else {
QSqlQuery query;
("select pwd from password");
();
if ((0).toString() == ui->pwdLineEdit->text()) {
QDialog::accept();
} else {
QMessageBox::warning(this, tr("密码错误"),
tr("请输入正确的密码再登录!"), QMessageBox::Ok);
ui->pwdLineEdit->clear();
ui->pwdLineEdit->setFocus();
}
}
}
void LoginDialog::on_quitBtn_clicked()
{
QDialog::reject();
}
当按下“登录”按钮并且输入的密码正确时执行QDialog::accept()函数,该函数会隐藏
对话框并将返回码设置为Accepted;当按下“退出”按钮时执行QDialog::reject()函数,该
函数会隐藏对话框并将返回值设置为Rejected。
这里使用了对话框的返回值来进行判断,如果返回值为QDialog::Accepted,则显示主界
面,否则退出程序
4.实现功能
(1)首先双击文件进入设计模式,然后分别右击“出售商品”、“商品入库”、“添
加商品”、“商品查询”和“修改密码”等按钮,选择“转到槽”,然后选择clicked信号,更
改相应槽函数如下:
// 出售商品按钮
- 62 -
Qter开源社区
void Widget::on_sellBtn_clicked()
{
ui->stackedWidget->setCurrentIndex(0);
}
// 商品入库按钮
void Widget::on_buyBtn_clicked()
{
ui->stackedWidget->setCurrentIndex(1);
}
// 添加商品按钮
void Widget::on_addBtn_clicked()
{
ui->stackedWidget->setCurrentIndex(2);
}
// 商品查询按钮
void Widget::on_queryBtn_clicked()
{
ui->stackedWidget->setCurrentIndex(3);
}
// 修改密码按钮
void Widget::on_passwordBtn_clicked()
{
ui->stackedWidget->setCurrentIndex(4);
}
(2)在各个页面上首先是选择商品的类型,当商品类型改变时会自动修改品牌列表。分别进
入各个页面,右击类型后面的Combo Box部件,选择“转到槽”,选择
currentIndexChanged(QString)信号,更改各个槽函数如下:
// 出售商品的商品类型改变时
void Widget::on_sellTypeComboBox_currentIndexChanged(QString type)
{
if (type == "请选择类型") {
// 进行其他部件的状态设置
on_sellCancelBtn_clicked();
} else {
ui->sellBrandComboBox->setEnabled(true);
QSqlQueryModel *sellBrandModel = new QSqlQueryModel(this);
sellBrandModel->setQuery(QString("select name from brand where type='%1'")
.arg(type));
ui->sellBrandComboBox->setModel(sellBrandModel);
- 63 -
Qter开源社区
ui->sellCancelBtn->setEnabled(true);
}
}
// 已有商品入库的商品类型改变时
void Widget::on_goodsTypeComboBox_currentIndexChanged(QString type)
{
if (type == "请选择类型") {
// 进行其他部件的状态设置
on_goodsCancelBtn_clicked();
} else {
ui->goodsBrandComboBox->setEnabled(true);
QSqlQueryModel *goodBrandModel = new QSqlQueryModel(this);
goodBrandModel->setQuery(QString("select name from brand where type='%1'")
.arg(type));
ui->goodsBrandComboBox->setModel(goodBrandModel);
ui->goodsCancelBtn->setEnabled(true);
}
}
// 新商品入库类型改变时
void Widget::on_newTypeComboBox_currentIndexChanged(QString type)
{
if (type == "请选择类型") {
// 进行其他部件的状态设置
on_newCancelBtn_clicked();
} else {
ui->newBrandLineEdit->setEnabled(true);
ui->newBrandLineEdit->setFocus();
}
}
// 查询商品类型改变时
void Widget::on_queryTypeComboBox_currentIndexChanged(const QString type)
{
if (type == "请选择类型") {
ui->queryBrandComboBox->setEnabled(false);
} else {
ui->queryBrandComboBox->setEnabled(true);
QSqlQueryModel *brandModel = new QSqlQueryModel(this);
brandModel->setQuery(QString("select name from brand where type='%1'").arg(type));
ui->queryBrandComboBox->setModel(brandModel);
}
}
- 64 -
Qter开源社区
(3)类似的,当商品品牌改变时要查询相应的内容,分别进入各个页面,右击品牌后面的
Combo Box部件,选择“转到槽”,选择currentIndexChanged(QString)信号,更改各个槽函
数如下:
// 出售商品的品牌改变时
void Widget::on_sellBrandComboBox_currentIndexChanged(QString brand)
{
ui->sellNumSpinBox->setValue(0);
ui->sellNumSpinBox->setEnabled(false);
ui->sellSumLineEdit->clear();
ui->sellSumLineEdit->setEnabled(false);
ui->sellOkBtn->setEnabled(false);
QSqlQuery query;
(QString("select price from brand where name='%1' and type='%2'")
.arg(brand).arg(ui->sellTypeComboBox->currentText()));
();
ui->sellPriceLineEdit->setEnabled(true);
ui->sellPriceLineEdit->setReadOnly(true);
ui->sellPriceLineEdit->setText((0).toString());
(QString("select last from brand where name='%1' and type='%2'")
.arg(brand).arg(ui->sellTypeComboBox->currentText()));
();
int num = (0).toInt();
if (num == 0) {
QMessageBox::information(this, tr("提示"), tr("该商品已经售完!"),
QMessageBox::Ok);
} else {
ui->sellNumSpinBox->setEnabled(true);
ui->sellNumSpinBox->setMaximum(num);
ui->sellLastNumLabel->setText(tr("剩余数量:%1").arg(num));
ui->sellLastNumLabel->setVisible(true);
}
}
// 已有商品入库的品牌改变时
void Widget::on_goodsBrandComboBox_currentIndexChanged(QString brand)
{
ui->goodsNumSpinBox->setValue(0);
ui->goodsNumSpinBox->setEnabled(true);
ui->goodsSumLineEdit->clear();
ui->goodsSumLineEdit->setEnabled(false);
ui->goodsOkBtn->setEnabled(false);
- 65 -
Qter开源社区
QSqlQuery query;
(QString("select price from brand where name='%1' and type='%2'")
.arg(brand).arg(ui->goodsTypeComboBox->currentText()));
();
ui->goodsPriceLineEdit->setEnabled(true);
ui->goodsPriceLineEdit->setReadOnly(true);
ui->goodsPriceLineEdit->setText((0).toString());
}
// 新商品品牌改变时
void Widget::on_newBrandLineEdit_textChanged(QString str)
{
if (str == "") {
ui->newCancelBtn->setEnabled(false);
ui->newPriceSpinBox->setEnabled(false);
ui->newNumSpinBox->setEnabled(false);
ui->newSumLineEdit->setEnabled(false);
ui->newSumLineEdit->clear();
ui->newOkBtn->setEnabled(false);
} else {
ui->newCancelBtn->setEnabled(true);
ui->newPriceSpinBox->setEnabled(true);
ui->newNumSpinBox->setEnabled(true);
ui->newSumLineEdit->setEnabled(true);
qreal sum = ui->newPriceSpinBox->value() * ui->newNumSpinBox->value();
ui->newSumLineEdit->setText(QString::number(sum));
ui->newOkBtn->setEnabled(true);
}
}
(4)当商品数量改变时,也要进行相应的操作,分别进入各个页面,右击数量后面的Spin
Box,选择“转到槽”,选择valueChanged(int)信号,更改相应槽函数内容如下:
// 出售商品数量改变时
void Widget::on_sellNumSpinBox_valueChanged(int value)
{
if (value == 0) {
ui->sellSumLineEdit->clear();
ui->sellSumLineEdit->setEnabled(false);
ui->sellOkBtn->setEnabled(false);
} else {
ui->sellSumLineEdit->setEnabled(true);
ui->sellSumLineEdit->setReadOnly(true);
qreal sum = value * ui->sellPriceLineEdit->text().toInt();
- 66 -
Qter开源社区
ui->sellSumLineEdit->setText(QString::number(sum));
ui->sellOkBtn->setEnabled(true);
}
}
// 已有商品入库数量改变时
void Widget::on_goodsNumSpinBox_valueChanged(int value)
{
if (value == 0) {
ui->goodsSumLineEdit->clear();
ui->goodsSumLineEdit->setEnabled(false);
ui->goodsOkBtn->setEnabled(false);
} else {
ui->goodsSumLineEdit->setEnabled(true);
ui->goodsSumLineEdit->setReadOnly(true);
qreal sum = value * ui->goodsPriceLineEdit->text().toInt();
ui->goodsSumLineEdit->setText(QString::number(sum));
ui->goodsOkBtn->setEnabled(true);
}
}
// 新商品数量改变时
void Widget::on_newNumSpinBox_valueChanged(int value)
{
qreal sum = value * ui->newPriceSpinBox->value();
ui->newSumLineEdit->setText(QString::number(sum));
ui->newOkBtn->setEnabled(true);
}
(5)在添加商品页面,当单价改变时也要更改金额,右击该页面单价后面的Spin Box,选
择“转到槽”,选择valueChanged(int)信号,更改相应槽函数内容如下:
// 新商品单价改变时
void Widget::on_newPriceSpinBox_valueChanged(int value)
{
qreal sum = value * ui->newNumSpinBox->value();
ui->newSumLineEdit->setText(QString::number(sum));
ui->newOkBtn->setEnabled(true);
}
(6)各个页面的确定按钮按下时要通过操作数据库执行一定的操作,下面分别右击各个页
面的“确定”按钮,选择“转到槽”,选择clicked()信号,修改相应的槽内容如下:
// 出售商品的确定按钮
void Widget::on_sellOkBtn_clicked()
{
- 67 -
Qter开源社区
QString type = ui->sellTypeComboBox->currentText();
QString name = ui->sellBrandComboBox->currentText();
int value = ui->sellNumSpinBox->value();
// cellNumSpinBox的最大值就是以前的剩余量
int last = ui->sellNumSpinBox->maximum() - value;
QSqlQuery query;
// 获取以前的销售量
(QString("select sell from brand where name='%1' and type='%2'")
.arg(name).arg(type));
();
int sell = (0).toInt() + value;
// 事务操作
QSqlDatabase::database().transaction();
bool rtn = (
QString("update brand set sell=%1,last=%2 where name='%3' and type='%4'")
.arg(sell).arg(last).arg(name).arg(type));
if (rtn) {
QSqlDatabase::database().commit();
QMessageBox::information(this, tr("提示"), tr("购买成功!"), QMessageBox::Ok);
} else {
QSqlDatabase::database().rollback();
QMessageBox::information(this, tr("提示"), tr("购买失败,无法访问数据库!"),
QMessageBox::Ok);
}
on_sellCancelBtn_clicked();
}
// 已有商品入库的确定按钮
void Widget::on_goodsOkBtn_clicked()
{
QString type = ui->goodsTypeComboBox->currentText();
QString name = ui->goodsBrandComboBox->currentText();
int value = ui->goodsNumSpinBox->value();
QSqlQuery query;
// 获取以前的总量
(QString("select sum from brand where name='%1' and type='%2'")
.arg(name).arg(type));
();
int sum = (0).toInt() + value;
- 68 -
Qter开源社区
// 获取以前的剩余量
(QString("select last from brand where name='%1' and type='%2'")
.arg(name).arg(type));
();
int last = (0).toInt() + value;
// 事务操作
QSqlDatabase::database().transaction();
bool rtn = (
QString("update brand set sum=%1,last=%2 where name='%3' and
type='%4'")
.arg(sum).arg(last).arg(name).arg(type));
if (rtn) {
QSqlDatabase::database().commit();
QMessageBox::information(this, tr("提示"), tr("入库成功!"), QMessageBox::Ok);
} else {
QSqlDatabase::database().rollback();
QMessageBox::information(this, tr("提示"), tr("入库失败,无法访问数据库!"),
QMessageBox::Ok);
}
on_goodsCancelBtn_clicked();
}
// 新商品的确定按钮
void Widget::on_newOkBtn_clicked()
{
QString type = ui->newTypeComboBox->currentText();
QString brand = ui->newBrandLineEdit->text();
qint16 price = ui->newPriceSpinBox->value();
qint16 num = ui->newNumSpinBox->value();
QSqlQuery query;
("select id from brand");
();
qreal temp = (0).toInt() + 1;
QString id;
if (temp < 10) {
id = "0" + QString::number(temp);
} else {
id = QString::number(temp);
}
- 69 -
Qter开源社区
// 事务操作
QSqlDatabase::database().transaction();
bool rtn = (QString("insert into brand values('%1', '%2', '%3', %4, %5, 0, %6)")
.arg(id).arg(brand).arg(type).arg(price).arg(num).arg(num));
if (rtn) {
QSqlDatabase::database().commit();
QMessageBox::information(this, tr("提示"), tr("入库成功!"), QMessageBox::Ok);
} else {
QSqlDatabase::database().rollback();
QMessageBox::information(this, tr("提示"), tr("入库失败,无法访问数据库!"),
QMessageBox::Ok);
}
on_newCancelBtn_clicked();
}
(6)各个页面的取消按钮按下时要进行部件状态设置操作,下面分别右击各个页面的“取
消”按钮,选择“转到槽”,选择clicked()信号,修改相应的槽内容如下:
// 出售商品的取消按钮
void Widget::on_sellCancelBtn_clicked()
{
ui->sellTypeComboBox->setCurrentIndex(0);
ui->sellBrandComboBox->clear();
ui->sellBrandComboBox->setEnabled(false);
ui->sellPriceLineEdit->clear();
ui->sellPriceLineEdit->setEnabled(false);
ui->sellNumSpinBox->setValue(0);
ui->sellNumSpinBox->setEnabled(false);
ui->sellSumLineEdit->clear();
ui->sellSumLineEdit->setEnabled(false);
ui->sellOkBtn->setEnabled(false);
ui->sellCancelBtn->setEnabled(false);
ui->sellLastNumLabel->setVisible(false);
}
// 已有商品入库的取消按钮
void Widget::on_goodsCancelBtn_clicked()
{
ui->goodsTypeComboBox->setCurrentIndex(0);
ui->goodsBrandComboBox->clear();
ui->goodsBrandComboBox->setEnabled(false);
ui->goodsPriceLineEdit->clear();
ui->goodsPriceLineEdit->setEnabled(false);
ui->goodsNumSpinBox->setValue(0);
- 70 -
Qter开源社区
ui->goodsNumSpinBox->setEnabled(false);
ui->goodsSumLineEdit->clear();
ui->goodsSumLineEdit->setEnabled(false);
ui->goodsOkBtn->setEnabled(false);
ui->goodsCancelBtn->setEnabled(false);
}
// 新商品入库的取消按钮
void Widget::on_newCancelBtn_clicked()
{
ui->newTypeComboBox->setCurrentIndex(0);
ui->newBrandLineEdit->clear();
ui->newBrandLineEdit->setEnabled(false);
ui->newPriceSpinBox->setEnabled(false);
ui->newPriceSpinBox->setValue(1);
ui->newNumSpinBox->setEnabled(false);
ui->newNumSpinBox->setValue(1);
ui->newSumLineEdit->setText("1");
ui->newSumLineEdit->setEnabled(false);
ui->newOkBtn->setEnabled(false);
ui->newCancelBtn->setEnabled(false);
}
(7)商品查询页面的“查询”按钮通过类型和品牌条件进行查询操作,下面右击“查询”
按钮,选择“转到槽”,选择clicked()信号,修改相应的槽内容如下:
// 查询按钮
void Widget::on_queryPushButton_clicked()
{
model->setTable("brand");
model->setHeaderData(0, Qt::Horizontal,tr("编号"));
model->setHeaderData(1, Qt::Horizontal,tr("品牌"));
model->setHeaderData(2, Qt::Horizontal,tr("分类"));
model->setHeaderData(3, Qt::Horizontal,tr("单价"));
model->setHeaderData(4, Qt::Horizontal,tr("总量"));
model->setHeaderData(5, Qt::Horizontal,tr("卖出"));
model->setHeaderData(6, Qt::Horizontal,tr("剩余"));
if(ui->queryBrandComboBox->isEnabled()) {
QString type = ui->queryTypeComboBox->currentText();
QString name = ui->queryBrandComboBox->currentText();
model->setFilter(QString("type='%1' and name='%2'").arg(type).arg(name));
}
model->select();
}
- 71 -
Qter开源社区
(8)修改密码页面的“确定”按钮通过操作数据库来修改密码,下面右击“确定”按钮,
选择“转到槽”,选择clicked()信号,修改相应的槽内容如下:
// 修改密码确定按钮
void Widget::on_changePwdBtn_clicked()
{
if (ui->oldPwdLineEdit->text().isEmpty() ||
ui->newPwdLineEdit->text().isEmpty()) {
QMessageBox::warning(this, tr("警告"), tr("请将信息填写完整!"),
QMessageBox::Ok);
} else {
QSqlQuery query;
("select pwd from password");
();
if ((0).toString() == ui->oldPwdLineEdit->text()) {
bool temp = (QString("update password set pwd='%1' where pwd='%2'")
.arg(ui->newPwdLineEdit->text()).arg(ui->oldPwdLineEdit->text()));
if (temp) {
QMessageBox::information(this, tr("提示"), tr("密码修改成功!"),
QMessageBox::Ok);
ui->oldPwdLineEdit->clear();
ui->newPwdLineEdit->clear();
} else {
QMessageBox::information(this, tr("提示"),
tr("密码修改失败,无法访问数据库!"),
QMessageBox::Ok);
}
} else {
QMessageBox::warning(this, tr("警告"), tr("原密码错误,请重新填写!"),
QMessageBox::Ok);
ui->oldPwdLineEdit->clear();
ui->newPwdLineEdit->clear();
ui->oldPwdLineEdit->setFocus();
}
}
}
(9)下面打开widget.h文件,添加类的前置声明:
class QSqlTableModel;
然后添加一个私有对象定义:
private:
QSqlTableModel *model;
(10)打开文件,添加头文件包含:
#include
- 72 -
Qter开源社区
#include
#include
然后在构造函数中添加一些初始化内容:
ui->stackedWidget->setCurrentIndex(0);
QSqlQueryModel *typeModel = new QSqlQueryModel(this);
typeModel->setQuery("select name from type");
ui->sellTypeComboBox->setModel(typeModel);
on_sellCancelBtn_clicked();
on_goodsCancelBtn_clicked();
on_newCancelBtn_clicked();
ui->goodsTypeComboBox->setModel(typeModel);
ui->newTypeComboBox->setModel(typeModel);
model = new QSqlTableModel(this);
ui->tableView->setModel(model);
ui->queryTypeComboBox->setModel(typeModel);
ui->queryBrandComboBox->setEnabled(false);
5.发布程序
(1)编译运行程序,选择编译运行Release版本程序(因为在实验6中可能只编译了Release
版本的MySQL驱动)。
(2)对程序进行测试,试验各种可能的情况,查看程序运行是否正确。
(3)打包发布程序。
思考题:
怎样使用Qt编写一个综合应用程序?
- 73 -
发布者:admin,转转请注明出处:http://www.yc00.com/web/1715613130a2644979.html
评论列表(0条)