一、文件IO
1. QFileDialog 文件对话框
Qt预设的用于选择文件或目录的对话框窗口类,继承自QDialog。QFileDialog本身不具备IO功能。
调用窗口通过静态成员函数:
此函数可以展示一个用于读取/保存单文件的对话框窗口。
参数1:父对象
参数2:窗口标题
参数3:基于哪个目录,默认为项目的工作目录
参数4:文件类型过滤器
返回值:用户选择的文件路径,如果选择失败,返回空字符串
2. QFileInfo 文件信息类
QFileInfo类用于获取文件信息。
常用函数如下所示。
- QFileInfo::QFileInfo(const QString & file)
构造函数,参数是文件路径,需要注意的是参数无论是内容,QFileInfo对象都可以创建。
- QDateTime QFileInfo::created() const
返回文件的创建日期和时间
- bool QFileInfo::exists() const
文件是否存在
- bool QFileInfo::isReadable() const
是否可读
- qint64 QFileInfo::size() const
文件大小,返回的单位是字节
3. QFile 文件读写类
QFile类是进行文件读写的类,QIODevice是Qt所有IO类的基类,因此QIODevice类规定了很多IO通用的基础接口。
QFile类的常用函数如下所示。
- QFile::QFile(const QString & name)
构造函数,参数为读写文件的路径
- bool QIODevice::open(OpenMode mode) [virtual]
打开文件读写的数据流,参数为打开的模式。
- bool QIODevice::atEnd() const [virtual]
是否读到文件尾
- QByteArray QIODevice::read(qint64 maxSize)
读取最大字节数的数据,参数是最大字节数,返回值是读取后的字节数组对象。
- qint64 QIODevice::write(const QByteArray & byteArray)
写出数据到文件,参数为需要写出的数据,返回值是实际写出的数据量,如果返回-1表示写出错误。
- void QIODevice::close() [virtual]
关闭数据流
- qint64 QIODevice::size() const [virtual]
获取可读的字节数
4. UI与耗时操作
在默认的情况下,程序员编写Qt程序只在一个线程(主线程)中运行。但是有时候这个线程会出现一些耗时操作(例如文件IO、网络、复杂算法等),这些耗时操作会导致主线程阻塞,此时用户发起的一些常规UI操作就无法得到及时的响应,此时操作系统检测一些关闭等UI操作无法及时响应则会弹出程序未响应窗口。
Windows等桌面操作系统会引导用户选择关闭还是等待。
解决方案就是使用多线程,主线程只执行UI相关操作,子线程执行耗时操作。
5. QThread 线程类(掌握)
5.1 复现未响应
QThread类是Qt的线程类,其中有一个静态成员函数:
- void QThread::msleep(unsigned long msecs) [static]
使当前线程强制睡眠,参数为睡眠时间,单位毫秒。
5.2 创建并启动线程
创建并启动一个线程的步骤如下:
1. 在Qt Creator中选中项目名称后,鼠标右键,点击“添加新文件”。
2. 在弹出的窗口中,按照下图所示配置自定义线程类信息。
3. 在“项目管理”界面,直接点击“完成”。可以在项目中看到,线程类已经创建完成。
4. 在自定义线程类中,覆盖QThread类中的run函数。
void QThread::run() [virtual protected]
此函数是子线程的起始点,此函数执行完成后,子线程也执行结束。
5. 在run函数中编写子线程要执行的代码,此函数不能包含UI操作。
6. 在主线程中创建子线程类对象,并调用start函数启动子线程。
void QThread::start(Priority priority = InheritPriority) [slot]
参数为线程执行的优先级。
5.3 优先级
不同的线程对象可以拥有不同的优先级,优先级代表cpu的一种选择偏向,具体取决于cpu对线程的调度。
除了使用start函数在启动时直接设置优先级外,当线程运行时,也可以使用下面的函数设置优先级;如果线程没有运行,此函数无效。
- void QThread::setPriority(Priority priority)
参数为不同的优先级。
5.4 线程停止
在实际的开发中尽量不要停止线程,本次提供两种停止的方式:
1. 调用terminate函数
void QThread::terminate() [slot]
强行停止线程执行
2. 给耗时操作循环体设置标志位,通过设置标志位的数值,停止循环,间接使run函数执行完毕,从而达到停止线程的效果。
可以子线程执行耗时操作(循环睡眠),主线程接收子线程操作的通知,在实际的开发中,主线程接收到子线程耗时操作的通知后可能会刷新UI显示(例如显示文件读写的进度),这种情况下需要使用信号槽进行两个线程之间的通信。
二、数据库
1. Qt数据库简介
Qt本身并不具备数据库,需要配合市面上的数据库产品才能使用。为了规范不同厂商数据库的操作方式,Qt为它们指定了一套统一的操作接口。
与Qt数据库操作相关的类有,
- QSqlDatabase
数据库操作连接类
- QSqlError
数据库错误信息类。
Qt调用数据库,当数据库本身产生错误时,会把错误信息传递给Qt,Qt会把错误信息封装为QSqlError类对象,以便于程序员获取。
- QSqlQuery
数据库操作类,用于执行SQL语句。
Qt的数据库相关的类使用前需要先在.pro项目配置文件中,添加sql模块。
2. 连接数据库
需要使用的函数如下所示。
- QSqlDatabase QSqlDatabase::addDatabase(const QString & type) [static]
获得一个数据库连接对象。
参数为数据库的类型,Qt支持以下数据库的连接。
QSQLite3作为比较小巧的关系型数据库产品,是Qt唯一内置的数据库,并且也内置了连接的驱动程序,可以直接使用上表左列的驱动名称连接。
- void QSqlDatabase::setDatabaseName(const QString & name)
设置数据库名称,此函数会因为连接的数据库类型而有不同的含义,对于SQLite数据库而言,此函数的参数表示数据库文件的名称,这是因为SQLite数据库通过单文件存储。
- bool QSqlDatabase::open()
打开数据库连接,返回值是打开的结果。如果打开失败,会通过lastError函数返回错误信息;如果打开成功可以通过close函数关闭连接。
数据库连接打开成功后,进入构建目录,可以看见数据库文件已生成。
- QSqlError QSqlDatabase::lastError() const
返回上一次数据库操作的错误信息对象,QSqlError类的text函数可以拿到错误信息的字符串。
3. 建表
参考建表语句:
CREATE TABLE teacher(
id INTEGER PRIMARY KEY,
name TEXT,
sex TEXT,
age INTEGER,
mclass TEXT);
使用函数:
- bool QSqlQuery::exec(const QString & query)
执行SQL语句,参数是要执行的SQL语句,返回值是执行的结果。
如果执行错误,错误信息可通过QSqlError QSqlQuery::lastError() const函数获得。
建表操作后,可以使用SQLiteSpy软件打开数据库文件。
4. 增删改查
增删改查的过程中,对于一些数据需要从UI上获取,这些获取后,按照以往的方式需要与SQL语句进行拼接,在交给Qt去执行。这样的做法可以实现功能,但是存在一些缺点:
- 拼接时容易出错
- 容易出现安全问题
Qt中使用预处理+数据绑定的方式解决上述问题。
需要先编写预处理的SQL语句,与普通SQL语句的区别在于,先使用占位符对需要传入的数据进行替换,占位符有两种写法:
- Oracle风格
使用英文冒号与列名结合的方式,例如:name
优点是后续数据绑定时可以乱序
- ODBC风格
使用?
优点是写法更简单。
相关函数如下。
- bool QSqlQuery::prepare(const QString & query)
预处理SQL语句,参数是符合格式的预处理语句,返回值是预处理结果。
Oracle风格的绑定函数,可以把参数绑定到预处理语句中。
参数1:占位符
参数2:占位符对应的值,QVariant兼容所有Qt常见类型
- bool QSqlQuery::exec()
执行预处理的SQL语句,返回值是执行的结果
- void QSqlQuery::addBindValue(const QVariant & val)
ODBC风格的绑定函数
参数:占位符对应的值
- bool QSqlQuery::next()
取出下一条记录,如果取出成功,则后移。
- QVariant QSqlQuery::value(int index) const
- QVariant QSqlQuery::value(const QString & name) const
取出当前记录的某列数据,参数是列序号,从0开始;参数是列名。
模糊查询可以做到只输入查询关键字的一部分就查询出符合格式的数据。
模糊查询使用关键字LIKE,配合两个通配符。
- %
匹配任意个数的字符
- _
匹配任意一个字符
【例子】查询姓张的老师信息。
SELECT * FROM teacher WHERE name LIKE '张%';
【例子】查询兴字辈儿的老师信息。
SELECT * FROM teacher WHERE name LIKE '_兴%';
【例子】查询名称中包含晓的老师信息。
SELECT * FROM teacher WHERE name LIKE '%晓%';
三、程序打包
1. 设置图标
给应用程序设置图标的步骤如下所示。
1. 找到一个图片,并转换为.ico图标格式,推荐分辨率256x256
PNG转ICO在线:
2. 给ico文件命名为合法格式,并放置到工作目录。
3. 在Qt Creator中选中项目名称,鼠标右键,点击“添加新文件”。
4. 在弹出的窗口中,按照下图所示进行操作。
5. 在弹出窗口中,输入文件名称,注意此文件的扩展名为.rc,必须输入。
6. 在项目管理界面,直接点击“完成”。可以看到项目中多个.rc文件,打开此文件。在rc文件中添加代码:
IDI_ICON1 ICON DISCARDABLE "XXX.ico"
其中XXX表示图标文件的名称。
7. 进入.pro项目配置文件,在其中增加
RC_FILE += XXX.rc
其中XXX是rc文件的名称。
8. 重新编译并运行项目,观察应用程序的图标是否成功设置。
2. Debug与Release模式
程序的构建有两种模式:Debug模式和Release模式,默认为Debug模式,可以通过Qt Creator的左下角切换两种模式。
Debug模式下,生成的可执行文件中包含很多调试信息,这样的程序运行速度比较慢,体积比较大,适合程序员开发使用。
进入构建目录的debug文件夹下,可以看到此模式下生成的可执行文件。
Release模式下,生成的程序一般不包含调试信息,虽然这样的程序不方便被调试,但是体积小,编译器会对代码做出优化,因此运行速度快,适合发布给用户使用。
切换到Release模式下构建一次项目后,进入构建目录的release文件夹下,可以看到此模式下生成的可执行文件。
无论是哪种模式,直接运行exe可执行文件都会报错。
可以看到exe的运行需要dll文件的支持。
3. 动态链接库 dll
程序的本体是exe文件,但是其API的调用需要依赖Qt的动态连接库文件,需要把可执行文件与动态连接库文件放置到同一个目录下,才能运行。
Qt中也包含了一个windeployqt的工具,此工具可以通过分析一个exe文件,得到绝大多数此文件所需的动态链接库。
在Win的菜单栏中,找到Qt下面的
定位exe所在的目录,输入下面的命令,回车即可。
windeployqt 程序名称.exe
提取dll完成后,进入到可执行执行文件所在的目录,再次执行,仍然报错。
缺啥手动补啥。
4. 打包
本次使用的打包工具是isetup,安装方式一直下一步即可。
打包的步骤如下:
1.
2.
3. 配置相关信息
4. 配置安装路径
5. 添加需要打包的文件
6. 配置开始菜单参数
7. 不配置安装许可
8. 选择安装程序的支持语言,当前版本不支持中文。
9. 配置安装包参数
10. 点击“Next”与“Finish”开始打包。
11.
12. 开始编译,编译完成后就可以使用安装包了。