一个稍微复杂的Qt程序
《第一个Qt程序》中使用 MainWindow 作为主界面,内置一个 QLabel 控件,所有代码都写在 main() 函数内部。本节我们将主要代码封装到一个类的内部,然后在 main() 函数中创建该类的对象,这貌似更加符合 C++ 规范。
1) MyMainWindow.h 文件代码:
Q_OBJECT 是一个宏,这种写法对初学者来说是非常陌生的,它是 Qt 自己的语法扩展。Qt 的这种做法像极了早期的 C++:
Qt 想要的功能 C++ 没有,怎么办?那就自己上,亲自实现这个功能!为了支持这些扩展功能,Qt 甚至实现了一个微型编译器——元对象编译器(Meta-Object Compiler, moc)。
C++ 为了保持程序运行的高效性,仅通过 RTTI(Run-Time Type Information,运行时类型识别)提供了非常简陋的内省机制,几乎没有用武之地。Qt 抛弃了 C++ 自带的内省机制,另起炉灶,创造了更加强大的元对象(meta object)系统,以此来支持完整的内省机制。
Q_OBJECT 宏就声明了 Qt 元对象系统必须的函数和成员变量,之后我们会用 moc 工具生成元对象系统的实体函数代码。继承 Qt 类时建议在类声明的开头添加 Q_OBJECT 宏,否则有时会出现莫名其妙的错误;如果你使用了信号和槽机制,Q_OBJECT 宏就是必须添加的,因为信号和槽依赖于元对象系统。
2) MyMainWindow.cpp 文件代码:
3) main.cpp 文件代码:
前面提到 Qt 元对象系统,Qt 是基于 C++ 开发的,而 C++ 本身并没有元对象系统。元对象系统是 Qt 专门为 C++ 做的扩展功能,用于支持非常强大的信号/槽机制、内省机制等,后面我们会详细讲解,本节我们重点学习 moc 工具的使用。下面逐步介绍编译链接本节程序的过程。
生成 main.exe 的整个流程
编写代码
我们在 D:\QtDemo 文件夹创建三个代码文件,分别是 MyMainWindow.h、MyMainWindow.cpp 和 main.cpp,各个文件的具体代码如下所示。1) MyMainWindow.h 文件代码:
#ifndef MYMAINWINDOW_H #define MYMAINWINDOW_H #include <QtWidgets/QMainWindow> #include <QtWidgets/QLabel> class MyMainWindow : public QMainWindow { Q_OBJECT public: MyMainWindow(); ~MyMainWindow(); private: QLabel *m_pLabel; }; #endifMYMAINWINDOW_H 可以防止头文件被重复包含,不了解的读者请猛击《防止C语言头文件被重复包含》。
Q_OBJECT 是一个宏,这种写法对初学者来说是非常陌生的,它是 Qt 自己的语法扩展。Qt 的这种做法像极了早期的 C++:
- C++ 在C语言的基础上发展而来,C++ 扩展了C语言的语法,早期的 C++ 代码都是先被转换为C语言代码,再使用C语言编译器编译。
- Qt 是基于 C++ 的,但是它对 C++ 的语法进行了扩展(比如信号和槽机制、内省机制等),并增加了一些关键字(例如 signals、slots、emit 等),在真正编译之前,扩展语法先被转换成 C++ 代码(通过 moc 工具),然后再使用 C++ 编译器编译。
Qt 想要的功能 C++ 没有,怎么办?那就自己上,亲自实现这个功能!为了支持这些扩展功能,Qt 甚至实现了一个微型编译器——元对象编译器(Meta-Object Compiler, moc)。
C++ 为了保持程序运行的高效性,仅通过 RTTI(Run-Time Type Information,运行时类型识别)提供了非常简陋的内省机制,几乎没有用武之地。Qt 抛弃了 C++ 自带的内省机制,另起炉灶,创造了更加强大的元对象(meta object)系统,以此来支持完整的内省机制。
Q_OBJECT 宏就声明了 Qt 元对象系统必须的函数和成员变量,之后我们会用 moc 工具生成元对象系统的实体函数代码。继承 Qt 类时建议在类声明的开头添加 Q_OBJECT 宏,否则有时会出现莫名其妙的错误;如果你使用了信号和槽机制,Q_OBJECT 宏就是必须添加的,因为信号和槽依赖于元对象系统。
2) MyMainWindow.cpp 文件代码:
#include "MyMainWindow.h" MyMainWindow::MyMainWindow(): QMainWindow(){ this -> setWindowTitle("MyMainWindow演示"); //设置标题 this -> resize(360, 140); //设置客户区大小 m_pLabel = new QLabel("新宝库", this); m_pLabel -> setGeometry(130, 50, 160, 30); //设置Label控件的几何尺寸 } MyMainWindow::~MyMainWindow(){ delete m_pLabel; m_pLabel = NULL; }该源文件里只有一个构造函数和一个析构函数。注意析构函数,它删除之前 new 的标签控件对象,并把指针设置为 NULL。
3) main.cpp 文件代码:
#include <QtWidgets/QApplication> #include "MyMainWindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); MyMainWindow w; w.show(); return app.exec(); }main 函数还是一如既往的简单,由于使用自定义的 MyMainWindow 作为主窗口类,所以是包含了 MyMainWindow.h 和 QApplication 两个头文件。
编译代码
需要手工编写的代码就这些,接下来的任务就是如何编译生成可执行程序了。前面提到 Qt 元对象系统,Qt 是基于 C++ 开发的,而 C++ 本身并没有元对象系统。元对象系统是 Qt 专门为 C++ 做的扩展功能,用于支持非常强大的信号/槽机制、内省机制等,后面我们会详细讲解,本节我们重点学习 moc 工具的使用。下面逐步介绍编译链接本节程序的过程。
1) 进入文件夹
打开 Qt 命令行工具,进入代码所在文件夹:cd /d D:\QtDemo
2) 使用 moc 工具
使用 moc 工具生成 MyMainWindow 类的元对象系统代码文件 moc_MyMainWindow.cpp :moc MyMainWindow.h -o moc_MyMainWindow.cpp
moc 工具会搜索头文件 MyMainWindow.h 里面所有的 Q_OBJECT 宏,并生成相应的元对象系统实际源代码,输出保存为 moc_MyMainWindow.cpp 文件。3) 编译和链接 .cpp 文件
加上刚才手动编写的 MyMainWindow.cpp 和 main.cpp,我们总共要编译三个 C++ 源码文件:g++ moc_MyMainWindow.cpp MyMainWindow.cpp main.cpp -std=c++0x -I"D:\Qt\5.9\mingw53_32\include" -L"D:\Qt\5.9\mingw53_32\lib" -lQt5Core -lQt5Gui -lQt5Widgets -o main
4) 运行 main.exe
生成 main.exe 之后,在 Qt 命令行工具里输入main.exe
命令就可以执行该程序,看到显示的效果。生成 main.exe 的整个流程
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算