1 QMake
是QT中独有的代码构建工具,一般来说,没有特殊要求,创建QT项目都是使用QMake
2 Qt中三个窗口部件的区别
2.1 QMainWindow
包含菜单栏、工具栏、状态栏
2.2 QWidget
一个普通的窗口,不包含菜单栏、状态栏,除了登录界面,新建项目时建议使用awidget,因为大部分的窗口可能都要做成无边框窗口,需要自定义标题栏,实现拉伸等。因此QMainwindow使用的场景不多
2.3 QDialog
对话框,常用来做登录窗口、弹出窗口(例如设置界面
3 lambda函数
3.1 概述
C++ lambda表达式的本质就是重载了 operator(),lambda是一个类,在调用时会进行编译展开,因此lambda表达式对象其实就是一个匿名的functor,所以lambda 表达式 也叫匿名函数对象。
Qt槽函数可以使用lambda函数来写
C++中lambda表达式的构成:
[捕获列表](形参列表)mutable 异常列表->返回类型 { 函数体 }
3.2 参数详解
捕获列表:捕获外部变量,捕获的变量可以在函数体中使用,可以省略,即不捕获外部变量。一共有三种捕获方式:值捕获、引用捕获和隐式捕获,
形参列表:和普通函数的形参列表一样。可省略,即无参数列表
mutable:mutable 关键字,如果有,则表示在函数体中可以修改捕获变量。根据具体需求决定是否需要省略。
异常列表:noexcept/throw(…),和普通函数的异常列表一样。可省略,即代表可能抛出任何类型的异常。
返回类型:和函数的返回类型一样。可省略,如省略,编译器将自动推导返回类型。
函数体:代码实现。可省略,但是没意义。
3.3 捕获方式
值捕获:不能在lambda表达式中修改捕获变量的值
引用捕获:使用引用捕获一个外部变量,需在捕获列表变量前面加上一个引用说明符&
隐式捕获:其实就是值捕获和引用捕获的其中一种
int main() { //值捕获 int value = 100; auto f = [value](int a, int b)->int { //value++; 值捕获中,捕获列表中的参数是不可以改变的 return a + b + value; }; cout << f(1, 2) << endl; // 引用捕获 auto f2 = [&value](int a, int b)->int { //引用捕获中捕获列表中的参数要使用引用形式 value++; //引用捕获中可以改变值 return a + b; }; cout << f2(1, 3) << endl; cout << "value = " << value << endl; //value为101 // 隐式捕获 //参数列表中为 = 表示是值捕获 //参数列表中为 & 表示是引用捕获 int age = 123; auto f3 = [&](int a, int b)->int { value++; age++; //应用捕获中可以改变值 return a + b; }; return 0; }
4 Qt信号槽与moc
moc 全称是 Meta-Object Compiler,也就是“元对象编译器“。Qt 程序在交由标准编译器编译之前,先要使用 moc 分析 C++源文件。如果它发现在一个头文件中包含了宏 Q_OBJECT,则会生成另外一个 C++ 源文件,这个源文件中包含了 Q_OBJECT宏的实现代码,这个新的文件名字将会是原文件名前面加上moc构成,这个新的文件同样将进入编译系统,最终被链接到二进制代码中去。
因此我们可以知道,这个新的文件不是“替换”掉旧的文件,而是与原文件一起参与编译。另外,我们还可以看出一点,moc的执行是在预处理器之前。因为预处理器执行之后,Q_OBJECT宏就不存在了。
可以这么理解,moc把Qt中一些不是C++的关键字做了解析,让C++编译器认识,例如slots,signals,emit等。moc会把这些重新编译解析。
运行moc指令,可以将带有Q_OBJECT宏的头文件进行代码翻译:
moc widget.h -o moc widget.cpp
moc.exe的路径:D:\VisualStudio\QT\5.15.2\msvc2019\bin\moc.exe。我们之前已经将此路径添加到环境变量Path中去了。
5 Qt半内存访问机制
参考:https://blog.csdn.net/lizun7852/article/details/88740970
子窗口可以通过指定父窗口的方式,来托管子窗口的内存,而父窗口又可以通过它的父窗口来托管自己的内存,一层一层,顶级窗口(QWidget类对象或者其派生类widgwt对象)一般在main函数中实例化为可以自动销毁空间的栈上对象,这样子窗口的空间就只需手动申请而不用管释放了。其中的底层实现大概是这样:当父窗口释放时,会在析构函数中遍历自己所有的子窗口,将它们释放。
所有的QObject类对象及其派生类对象都可以通过指定父对象来托管内存,QWidget继承自QObject,所以它及其派生类对象能够使用内管管理机制。
那么所有的子对象只能在父对象销毁的时候才能一起销毁,势必会造成内存驻留,能不能自己来销毁呢?当然开发者也可以使用delete来销毁子对象,但是不推荐这种用法,因为QObject对象远比普通的类对象复杂的多,QObject底层实现在我们不知道的情况下,正进行着一些工作。如果这个时候使用delete强制释放,会造成一些不可预知的错误。一般推荐使用deleteLater函数,进行子对象的安全释放,它会等待所有事情都处理完毕后才释放。
这也就是为什么之前,当我们在创建对象时,一般是这样的写法:TestWin tw = new TestWin(this),也就是指定父指针为this(一般为当前的窗口)。
6 解决Qt中文乱码
Qt对中文的支持不是很好,使用Qtcreator会出现各种乱七八糟的中文乱码问题,如何处理这种问题?
- 粘贴别人的代码时,现在记事本里"过一遍”,再贴到Qtcreator
- 使用u8,也就是在中文前都加上u8。例如:ui.pushButton->setText(u8"你好”)
- 不使用atcreator开发,直接使用vs2019
- 在涉及到中文的文件中,在其最开头写上一句:#pragma execution character set(“utf-8”)
- QtCreator — 选项 — 文本编辑器 — UTF8 BOM总是删除
点击确定即可。
7 总结
在代码的舞台上翩翩起舞, Qt,如诗如画,编织梦的彩虹。
跨越平台的轻盈舞姿, 文档的琴音,灵感的涟漪。
模块的花瓣,细腻而丰满, 开发者的心灵,在那里盛开。
清新而深邃,如林中明月, Qt,用优雅的笔触,谱写未来的篇章。
渴望挑战Qt的学习路径和掌握进阶技术?不妨点击下方链接,一同探讨更多Qt的奇迹吧。我们推出了引领趋势的💻QT专栏:《QT从基础到进阶》 ,旨在深度探索Qt的实际应用和创新。🌐🔍