简介
- QT 应用程序开发 理论基础
怎么理解Qt的信号与槽机制
Qt的信号与槽机制是Qt中最重要的特性之一,它用于实现对象间的通信。在Qt中,信号与槽是事件驱动的核心,允许对象在特定事件发生时,向其他对象发出信号,并触发与之相关的槽函数。理解信号与槽机制可以帮助你更好地掌握Qt框架中的对象交互方式。
1. 信号(Signal)
信号是由Qt对象发出的,用于表示某个事件的发生或状态的变化。例如,一个按钮的点击事件就是一个信号。当按钮被点击时,它会发出一个信号。
信号不需要知道谁接收它,也不需要直接与接收者沟通。它只负责“发出”事件通知,告诉其它对象事件已经发生。
2. 槽(Slot)
槽是一个普通的成员函数,用于响应信号。当某个信号发出时,与该信号相关联的槽函数会被自动调用。槽可以是任何符合函数签名的普通成员函数,也可以是全局函数或lambda表达式。
槽的作用是处理信号发出的事件,并做出响应。
3. 连接信号与槽
信号与槽之间通过QObject::connect()
函数进行连接。当信号发出时,Qt框架会自动找到连接的槽并执行它。
1 | connect(sender, SIGNAL(clicked()), receiver, SLOT(onButtonClick())); |
在这个例子中,当sender
(例如一个按钮)发出clicked
信号时,receiver
的onButtonClick()
槽函数会被调用。
4. 自动连接
在Qt中,如果信号和槽的参数类型匹配,Qt会自动进行信号和槽的连接,而不需要显式调用connect()
。例如,QPushButton
有一个clicked()
信号,它和QDialog
中的accept()
槽可以自动连接。
5. 信号与槽的参数
信号和槽可以传递参数。信号的参数会传递给槽,槽函数的参数类型必须与信号的参数类型匹配。比如:
1 | connect(sender, SIGNAL(valueChanged(int)), receiver, SLOT(updateValue(int))); |
在这个例子中,当sender
的valueChanged
信号发出时,int
类型的参数会传递给receiver
的updateValue(int)
槽。
6. 信号与槽的特性
- 类型安全:Qt的信号与槽机制是类型安全的,即只有信号和槽参数类型匹配时,连接才会成功。
- 异步:信号和槽的调用是异步的,槽函数会在信号发出时被自动调用,线程间通信时也可以使用信号与槽机制。
- 多个连接:一个信号可以连接多个槽,多个信号可以连接到同一个槽。
7. 应用场景
- UI响应:比如按钮点击、鼠标事件等。
- 跨线程通信:信号与槽机制可以跨线程传递消息,帮助你在不同线程间传递数据或通知。
- 自定义事件:在开发中自定义信号与槽,处理特殊的业务逻辑。
总结来说,Qt的信号与槽机制是一种松耦合的通信方式,使得对象之间的交互变得更加灵活和可维护。通过这种机制,不同的对象之间能够相互传递信息而无需了解彼此的具体实现。
QT按钮组件
- QT中有六种按钮组件,分别是按压按钮QPushButton、工具按钮QToolButton、单选按钮QRadioButton、多选按钮QCheckBox、命令链接按钮QCommandLinkButton、按钮盒QButtonBox
QPushButton
QPushButton组件简介
- QPushButton组件用于接受用户点击事件,能够显示提示字符串,是功能性组件,需要父组件作为容器,能够在父组件中进行定位,用于执行命令或触发事件。
- QPushButton的类继承如下:
- QPushButton :public QAbstractButton :pubic QWidget :public QObject, public QPaintDevice
QPushButton组件属性
- QPushButton 组件属性设置选项:
- A、name:组件对应源代码中的名字。
- B、text:组件对应图形界面中显示的名字。
- C、font:设置text的字体。
- D、enabled:组件是否可用。
QPushButton组件常用成员函数
1 | QPushButton::QPushButton(const QString &text,QWidget *parent,const char *name = 0); |
- 构造一个名称为name,父对象为parent并且文本为text的按压按钮。
1 | void QAbstractButton::setText(const QString &) |
- 设置按钮上显示的文本。
1 | QString QAbstractButton::text()const |
- 返回按钮上显示的文本。
1 | void QAbstractButton::pressed()[signal] |
- 当按下按钮时,发射信号。
1 | void QAbstractButton::clicked()[signal] |
- 当单击按钮时,发射信号。
1 | + void QAbstractButton::released()[signal] |
- 当释放按钮时,发射信号。
Qt程序需要配置那些内容
- Qt的几个编译工具: moc, uic, rcc.这几个工具在Qt Assistant中都可以直接搜索到介绍界面,下面简单说一下各自的功能
- moc: 元对象编译器(Meta Object Compiler),用来处理带有Q_OBJECT宏的类。我们在声明class的时候,继承QObject,再私有声明Q_OBJECT宏就可以使用Qt的信号和槽了,实际上是Qt利用moc将各个类所需要的元对象代码(meta-object code)补充好了。(moc读取一个头文件,补充其中带有Q_OBJECT宏类的元对象代码,一般生成一个moc_ClassName.cpp文件)
- uic: 用户界面编译器(User Interface Compiler),用来编译ui界面文件的
- rcc: 资源编译器(Resource Compiler),把qrc文件编译成对应的C++代码
- 所以在CMake工程中使用Qt首先要搞明白如何调用这些工具
moc uic rcc 自动调用
首先对于 moc uic rcc处理的方法
1
2
3set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)设置了这几个变量之后,会在需要时自动调用这几个编译器。
在添加 exe 时的语法:
1
add_executable(TestQtCMake WIN32 src/main.cpp src/mainWindow.cpp src/mainwindow.h src/mainwindow.ui)
其中 WIN32 的参数可能需要提示一下
- 如果提供了 WIN32,则将设置WIN32_EXECUTABLE变量为ON,此时将生成一个界面程序而不是控制台程序。
添加Qt模块和生成执行文件
添加库,使用了 find_package()函数,示例如下
1
find_package(Qt5 COMPONENTS Widgets REQUIRED)
首先,要使用find_package()函数,需要提供一个.cmake文件,如何让CMake知道这个文件,可以采用两个方法
- 设置环境变量CMAKE_PREFIX_PATH为Qt5安装位置,这是官方Qt-CMake教程中的推荐做法
- 设置CMake中Qt5_DIR变量,值为QT5Config.cmake文件的位置。示例如下
1
set(Qt5_DIR D:\Qt514\5.14.0\msvc2017_64\lib\cmake\Qt5)
从上方目录可以看出来,这个.cmake文件是不同Qt版本和不同编译平台都有一套,所以对于官方推荐做法笔者并不是很推荐,难不成当需要换平台的时候还需要去改环境变量
将Qt库链接到可执行文件
1
target_link_libraries(TestQtCMake Qt5::Widgets)
运行时依赖处理
- 对于缺少dll文件,可以在环境变量中是设置Path,把Qt的bin目录添加进来
- 在windows平台使用官方的 windeployqt 工具,就在上述的bin目录下,传入exe文件路径就可以将该exe依赖的Qt文件全部打包到目录下,命令示例
1
windeployqt.exe TestQtCMake.exe
小结
- 要在CMake中使用Qt,需要以下几步
- 设置变量CMAKE_AUTO***为ON以启动 rcc uic moc编译器
- 设置变量QT5_DIR变量定位.cmake文件,使用find_package()函数定位Qt的库文件,使用target_link_libraries()函数链接Qt库
- 使用windeployqt工具打包依赖项