qt信号和槽
信号和槽
信号和槽本质上是两个类在进行通信。
信号或是传递值,或者是传递动作变化,槽函数响应信号或是接受值,或者根据动作变化来做出对应操作。
信号本质
信号是由于用户对窗口或者控件做了操作,导致窗口或者控件产生了某个特定事件,这时候对应的窗口类会发出某个信号,以此对用户的挑选做出反应。
信号是qt对象中特殊的函数,本质上是一种函数指针,事件发生时调用,不是在信号所属的对象中直接执行。
信号的呈现形式就是函数,也就是说某个事件产生了,qt框架会调用某个对应的信号函数,通知使用者。
槽的本质
槽的职责是对qt框架中产生的信号进行处理。
槽是qt对象中普通成员函数,用于处理信号发生时的动作。一个槽可以连接一个或者多个信号,当信号触发时,与之连接的槽会被调用。
信号和槽机制优点
①类型安全:需要关联的信号和槽的签名必须是等同的。
②松散耦合:槽和信号不需要知道对方(信号不用知道是哪个槽接收的,槽不用知道哪些信号关联自己)
连接
连接是信号和槽之间的桥梁,它将一个信号与一个槽相关联。当信号发生时,连接会调用与之关联的槽。连接的建立通常通过函数实现。
信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:
1 | QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot())); |
connect() 是 QObject 类的一个静态函数,而 QObject 是所有 Qt 类的基类,在实际调用
时可以忽略前面的限定符,所以可以直接写为:
1 | connect(sender, SIGNAL(signal()), receiver, SLOT(slot())); |
其中, sender 是发射信号的对象的名称, signal() 是信号名称。信号可以看做是特殊的函数,需要带括号,有参数时还需要指明参数。 receiver 是接收信号的对象名称, slot() 是槽函数的名称,需要带括号,有参数时还需要指明参数。
SIGNAL 和 SLOT 是 Qt 的宏,用于指明信号和槽,并将它们的参数转换成为相应的字符串。
###创建一个UI项目
点击mainwindow.ui文件进入ui界面设计地步。
ui界面英文含义
Layouts | 布局 |
---|---|
vertical Layouts | 垂直布局 |
Horizontal Layouts | 水平布局 |
grid Layouts | 网格布局 |
form Layouts | 表格布局 |
Horizontal spacer | 水平部件 |
vertical spacer | 垂直部件 |
push button | 下压按钮 |
tool button | 工具按钮 |
radio button | 选择按钮 |
check button | 复选按钮 |
command check button | 命令链接按钮 |
dialog button box | 对话框按钮 |
list view | 列表视图 |
tree view | 树视图 |
table view | 表视图 |
column view | 列视图 |
undo view | 撤销视图 |
widget | 控件 |
显示hello world,把控件中的文本控件拽出,并打字hello world就可以编译运行了。 | |
创建一个简单的UI按键项目 | |
将控件push button 拿出,打字关闭程序,这时候就要将控件以及信号槽连接。 | |
![]() |
|
![]() |
|
选择按钮的 clicked()信号,将其连接 MainWindow 对象的 close()槽。这样就完成了信号与槽的连接。 | |
在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT(特别重要)。 | |
当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。 | |
只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。 | |
总结如下图, 可以看到发送者与发送的信号是在一起的,接收者与接收的信号/槽是在一起的。 它们不能在 connect()方法里写乱顺序! 由发送者发送出信号到接收者用信号/槽接收。 |
如何在项目中创建槽
创建槽的方法也很简单, 也是直接在 mianwindow.h 里直接声明槽,在 mianwindow.cpp 里实现槽的定义, 声明槽必须写槽的定义(定义指函数体的实现),否则编译器编译时将会报错。
槽有以下特点:
槽可以是任何成员函数、普通全局函数、静态函数
槽函数和信号的参数和返回值要一致
mainwindow.h 添加槽函数后的代码
1 |
|
在 mainwindow.cpp 里 实 现 声 明 的 槽 函 数 void changeButtonText(); 和 voidpushButtonClicked();。 同时还实例化了 pushButton 对象。代码如下。
mainwindow.cpp 添加槽的实现代码
1 |
|
如何在项目中连接信号与槽
1 | connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked())); |
注意,发送信号的对象,和接收的信号的对象。 因为我们 pushButtonClicked()是本类里定义的槽,所以用 this 来接收。同理, pushButtonTextChanged()也是本类定义的信号。所以发送者写成 this。 changeButtonText()也是本类的槽函数,所以接收槽的对象也是 this。
在 mainwindow.cpp 中信号槽连接的代码如下。
mainwindow.cpp 实现连接信号槽
1 |
|