知识点
设计模式
- 创建型模式
- 结构型模式
- 行为模式
C++
- 指针和引用
STL
- 容器
- 迭代器
- 算法
- 仿函数
- 适配器
- 空间配置器
智能指针
- unique_ptr
- shared_ptr
Qt
-
元对象系统
- QObject基类
- Q_OBJECT()宏
- moc元对象编译器
-
信号与槽机制
- 原理:signals/slots - staticMetaObject - connect - 存放至map - emit触发 - active函数
- 优点:
- 缺点:
-
QThread
-
QTcpServer
-
QTcpSocket
一、Qt框架概述
1. 什么是Qt?
Qt是一个用C++编写的、成熟的、跨平台的GUI工具包,它是挪威Trolltech公司的产品,该公司为商业市场开发、销售和支持Qt及其相关软件。
Qt作为一个出色的软件框架,除了为应用程序提供GUI库,还提供了容器、输入输出、数据库、多线程、网络、三维图形等开发工具,十分强大。
Qt除了价格高昂的商用版本,还对自由软件社区提供了免费开源版本。
2. Qt的优点
-
跨平台
Qt的第一大优点,也是最令人印象深刻的特点就是它的跨平台性。
Qt支持Linux、类UNIX系统、Windows、Mac OS、甚至嵌入式平台。
Qt对于每一种操作系统平台,都提供了对应的底层类库,也就是在OS层和应用层之间增加了一个“平台适应层”,而对应用程序提供出来的接口时一致的。所以同样一套代码,不管放在Linux还是Windows,几乎不用改动就可以通过编译,此特性大大方便了软件的移植。 -
信号槽机制
信号与信号处理时GUI应用程序用来相应用户输入的主要机制,也是一个GUI库的核心特征。
Qt的信号处理机制由 信号 和 槽 构成。使用信号槽功能的类需要在类声明中添加 Q_OBJECT 宏声明,然后使用 QObject::connect() 函数进行连接,它明确地将信号和信号处理函数联系了起来。

-
Qt对象树
Qt对象之间是可以存在父子关系的。父对象会保存一个子对象链表,记录所有指向其子对象的指针,同时子对象也会保留指向父对象的指针。当一个父对象被析构时,其子对象也会被析构。
所以销毁一个对象,它的所有子孙后代对象都会被销毁,表现在Qt对象树上就是删除一个节点,那这个节点下的整个分支都会被删除。这种特性让开发人员在一个对象下new出若干子对象后,不需要手动去delete,只需要销毁一个父对象,它们都会被自动销毁,大大减轻开发人员的负担。
使用此特性时仍需注意的问题: 对象树和析构函数冲突 -
在线帮助系统
由于Qt提供的封住类和接口十分丰富,Qt Creator 在文本编辑器中提供了在线帮助系统,只需要选中要查询的内容,按下F1,即可弹出相应的帮助页面,极大地减少了查询和学习的时间。

二、Qt体系
1. Qt模块图

2. Qt继承树

3. Qt学习路线图

三、Qt编程练习
Spreadsheet 制作一个电子表格
项目总览
-
项目介绍
该项目会创建一个电子表格,功能类似Excel表格。
有基本的单元格编辑,复制,剪切,删除等功能。
有批量复制,搜索,排序等进阶功能。
有保存文件,打开文件,展示最近文件的功能。 -
所有文件
总文件个数17,总代码量约1800行

-
主窗口类 (继承于QMainWindow类)
mainwindow.h
mainwindow.cpp
主窗口类负责管理整体的布局,生成顶部工具栏以及快捷按钮,并且包含了提供核心功能的电子表格。主窗口还负责文件的保存与读取,以及提供第二级功能弹窗。

-
表格类 (继承于QTableWidget类)
spreadsheet.h
spreadsheet.cpp
表格类只生成由单元格组成的空白表格,有CCell单元格类作为私有成员。表格类的主要意义是接收输入(键盘、鼠标)并显示内容,以及提供所有跟表格内容有关的操作,比如拷贝、粘贴和剪切单元格,完成公式的计算,打开文件后的表格显示,从表格中读取数据,搜索数据等等…

-
单元格类 (继承于QTableWidgetItem,能很好地与表格类配合)
cell.h
cell.cpp
单元格类是最小的单元,所有数据最终都要通过它来显示和返回,它主要提供公式设置和解析的功能。

-
搜索对话框类 (继承于QDialog类)
sortdialog.h
sortdialog.cpp
在主窗口的Edit菜单点击Find搜索选项,或者按下快捷栏的Find按钮,都会弹出搜索弹窗。该窗口除了提供基本的搜索功能外,还增加了两个细微的操作来增加搜索的精确性:反向搜索和大小写感。搜索时勾选该选项(CheckBox)即可。只有当输入框中内容满足一定条件,Find按钮才会被激活,这里用到了Qt提供的正则表达式。

-
跳转对话框类 (继承于QDialog类)
gotocelldialog.ui
ui_gotocelldialog.h
gotocelldialog.cpp
该对话框的作用很简单,跳转到用户指定的单元格(比如A21、H55)。
(创建此对话框时用到了Qt Designer,因此生成了对应的ui文件)


-
排序对话框类 (继承于QDialog类)
sortdialog.ui
ui_sortdialog.h
sortdialog.cpp
该对话框提供对选中区域的排序功能,所有被选中的列号都会被加载进Column选项,你可以任选一列进行排序,按下more按钮,允许你再选择两列进行排序,这里对more键的toggle信号和后两个设置框的visible属性作了信号槽连接。
(创建此对话框时用到了Qt Designer,因此生成了对应的ui文件)



关键代码分析
- 主窗口功能 - 另存为SaveAs
以下是SaveAs操作会调用到的三个函数
在主函数中,SaveAs作为槽函数,在SaveAsAction被触发后调用。此函数调用 QFileDialog类 提供的 getSaveFileName 函数,会弹出一个已封装好的文件保存对话框,可以在参数列表中设置标题、保存类型。
保存后会返回文件名filename,为了之后交给spreasheet以保存当前数据内容。所以在return处调用saveFile私有函数
bool MainWindow::saveAs()
{
QString filename = QFileDialog::
getSaveFileName(
this,
tr("Save Spreadsheet"),
tr("Spreadsheet files (*.sp)"));
if (filename.isEmpty()) {
return false;
}
return saveFile(filename);
}
saveFile函数把filename交给spreadsheet,让其把表格中的数据写入,若写入成功,则设置为当前文件并给出提示。
bool MainWindow::saveFile(const QString& filename)
{
if (!spreadSheet->writeFile(filename)) {
statusBar()->showMessage(tr("Saving canceled"), 2000);
return false;
}
setCurrentFile(filename);
statusBar()->showMessage(tr("File saved"), 2000);
return true;
}
在CSpreadSheet类中完成数据写入操作。先用文件名构造一个 QFile 对象,然后调用open打开,若文件打开成功,则以此创建一个 QDataStream 数据流对象。最开始写入的MAGIC_NUMBER用于标识.sp文件,在读取数据的时候需要通过判断文件头来确定是否是sp文件。接着,通过遍历表格,将有公式的行号、列号和公式写入数据流。在此期间,将鼠标设为等待状态图形。
bool CSpreadSheet::writeFile(const QString& filename)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::warning(this, tr("Spreadsheet"),
tr("cannot write file %1:\n%2.")
.arg(file.fileName())
.arg(file.errorString()));
return false;
}
QDataStream out(&file);
out.setVersion(QDataStream::Qt_5_12);
out << quint32(MAGIC_NUMBER);
QApplication::setOverrideCursor(Qt::WaitCursor);
for (int row = 0; row < rowCount(); ++row) {
for (int col = 0; col < columnCount(); ++col) {
QString str = formula(row, col);
if (!str.isEmpty()<

本文深入介绍了Qt框架,包括其跨平台性、信号槽机制、对象树和在线帮助系统。通过一个电子表格应用的实战案例,展示了如何使用Qt进行GUI编程,涉及文件操作、表格交互、搜索及跳转功能。此外,文章还提供了详细的代码分析,涵盖了文件读写、菜单创建、单元格操作等关键功能。

15万+

被折叠的 条评论
为什么被折叠?



