以前学过Qt,但只是为了学分,现在重学。
1. 认识Qt应用程序框架
直接新建一个项目后,自动生成了一下文件,下面一个个理解。
(1)main.cpp
main.cpp中特别的是QApplication a,和 a.exec();
如果不构造 QApplication 对象,直接编译并运行,
结果:
成功生成可执行文件,并且成功执行,但立即退出,并打印异常信息:
QWidget: Must construct a QApplication before a QWidget
上面实验说明 QApplication 对象被 QWidget 对象使用。
此外,将 a.exec(); 换成死循环。
结果:
QWidget会显示,但是无法响应用户操作。
经过上面两个实验,可以得出下面结论:
QApplication 被 QWidget 调用,QApplication 会捕捉用户输入,将其传给 QWidget。
(2).pro文件
QT += core gui
这是加入链接模块。
问题是如何知道需要什么模块呢?
对使用的类按F1就可以获得,
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
这是兼容Qt4以上版本
TARGET = 01_test
这是指定目标名称,也就是最终生成的可执行文件名称
TEMPLATE = app
生成应用程序,其他二进制文件
SOURCES += \ main.cpp \ widget.cppHEADERS += \ widget.h
类似Makefile
(3)Qt的生成应用程序的过程
发现Qt生成应用程序有两步:qmake 和 构建
实验发现 qmake 是生成指导编译链接的Makefile,和建立两个文件夹debug和release
构建应该就是运行makefile
2. 父对象与子对象
父子对象不是继承关系,有点像组合。
大概有三个性质:
(1)父子对象机制是在QObject类中实现的,只有继承了QObject才能使用父子对象机制。
(2)父对象show时,子对象也会show,但是子对象不能单独show,子对象的坐标是相对于父对象的。
(3)父对象析构时,会先析构其子对象,子对象会析构孙子对象。
3. 信号与槽
信号与槽是观察者模式,当控件发现自己的某个事件发生后就发出信号,信号以广播形式发送,谁对该信号感兴趣就调用connect函数将信号与自己的槽函数绑定,只要信号发生就回调槽函数。
connect(sender &Sender::signal, receiver, &Receiver::slot);
(1)关于内存分配
connect 之前,释放 sender 内存,程序运行时出错, 释放 receiver,程序运行不会报错。
connect 之后,释放 sender,程序正常运行,释放receiver,程序正常运行,这说明connect可以通过释放sender或receiver取消。
(2)多次运行相同connect
当信号发出后,会触发多次槽函数。
其他:
(1)只有继承了 QObject类并且添加宏Q_OBJECT才能使用信号槽。
(2)信号无函数体,槽函数可以为任何函数,若槽函数为成员函数,会受访问权限影响
(3)信号槽可以有参数,但槽函数参数应保证能正确接受信号参数。
4. Lambda表达式
C++11中的Lambda表达式用于定义并创建匿名的函数对象。
格式:
[函数对象参数](操作符重载函数参数)mutable或exception ->返回值{函数体}
[]:
标识Lambda的开始,
确定函数对象参数(或者说是函数对象的成员函数),注意只能将 Lambda 可见范围内的变量作为成员函数。
=:
以传值的方式,将Lambda所有可见变量传入,并且为只读属性。
&:
以引用方式。将所有可见变量传入。
this:
只将this指针传入
a:
只将指定变量a以传值方式传入。
&a
只将变量a以引用方式传入
mutable:
以传值方式传入的变量可写。
->返回值类型
当返回类型为void,或只有一处返回,编译器可以推断出返回类型,所以可以省略。