【Qt】信号与槽
创始人
2025-01-15 12:33:39
0

目录

一. 什么是信号/槽 

二. 连接信号与槽

1. 代码实现

Qt4版本的写法

Qt5写法

2. 图形化开发

三. 自定义信号

四. 带参数的信号&槽

五. 断开信号与槽的连接

六. lambda表达式的槽函数


如果一个类要使用信号与槽机制,需要在声明处使用Q_OBJECT宏

一. 什么是信号/槽 

信号(Signal)和槽(slot)是Qt的一个强大的机制,用于处理对象之间的通信。

允许一个对象(发送者)发出信号,另一个对象(接受者)在该信号被发出时执行特定的槽函数

  • 信号 

    ​​​​​​​ssca

    信号的图标是

  •  

    ​​​​​​​槽是普通的成员函数,用于响应信号发出的事件

    槽可以是任何公共的函数,不同于信号,槽需要定义实现

    槽的图标是​​​​​​​

二. 连接信号与槽

1. 代码实现

在Qt中,通过QObject::connect()函数将信号与槽关联起来,实现控件对象之间的通信

示例:针对 button 这个按钮,点击后,改变窗口标题

Qt4版本的写法

注意,connect的第二个参数和第四个参数都是const char*,但调用时,我们传参都是函数指针。其实const char*的connect函数是Qt4的写法,其在调用时还需要对参数进行转换

//Qt5写法 connect(button, &QPushButton::clicked, this, &Widget::handleClicked); //Qt4写法 connect(button, SIGNAL(&QPushButton::clicked), this, SLOT(&Widget::handleClicked));

SIGNAL宏和SLOT宏,将函数指针的类型转化为const char*;

在槽函数声明时,也有独特的关键字——slots

访问限定符(public/protected/private) + slots  其后的成员函数都会被qmake识别为槽函数

Qt5写法

在Qt5中,使用了泛型编程,对connect函数做了重载 

 需要保证signal信号时sender的成员函数,slot是receiver的成员函数,否则会编译出错

2. 图形化开发

将按钮拖拽到程序界面,右键按钮控件,选择转到槽

会显示当前按钮控件都有哪些信号——选择clicked()

Qt会帮我们完成槽函数的声明和定义,只需要我们实现具体功能即可

 实际上,是qmake生成的ui_widget.h文件中调用了connectSlotsByName,帮我们关联和信号与槽,如果更改自动生成的槽函数的函数名,connectSlotsByName将无法完成关联。自动生成的槽函数的命名指明了信号产生者和信号类型

三. 自定义信号

在Qt中,信号本质也是函数,Qt允许用户自定义信号,但只能声明,信号的实现要交由Qt实现。信号函数的定义,是Qt在编译过程中自动生成的,我们无法干预,其实现要配合Qt框架做很多既定操作。

Qt规定,信号函数的返回值必须是void,参数随意,可无参数,也可通过参数进行重载

定义信号函数的关键字——signals

发送信号的关键字——emit

但是在Qt5后,又做了更新。将实际发送信号的逻辑直接写在了信号的定义中。所以不用emit,而是直接调用信号函数,也可以发送信号 

四. 带参数的信号&槽

传参可以起到服用代码的效果,如果多个逻辑,逻辑整体一致,只有涉及的数据不同,那可以通过函数-参数来服用代码,在不同场景传入不同参数即可,公有一套信号与槽

 Qt规定:信号的参数个数 >= 其关联的槽的参数个数

一个槽函数,可能关联多个信号,如此可以使得信号和槽的绑定更加灵活,多余的参数直接丢弃即可,但必须确保槽每个参数都有传参

示例:

#ifndef WIDGET_H #define WIDGET_H  #include   QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE  class Widget : public QWidget {     Q_OBJECT  signals:     void mySignal(const QString&);//信号函数的声明  public:     Widget(QWidget *parent = nullptr);     ~Widget();     void handleMySignal(const QString&);//槽函数声明  private:     Ui::Widget *ui; }; #endif // WIDGET_H

五. 断开信号与槽的连接

Qt还提供取消已关联的信号与槽的方法——disconnect函数

disconnect的使用与connect非常类似,实际使用比较少,大部分情况下,关联好的信号与槽就不会再做改变了

其参数同connect,只是实际效果不同:

connect是将sender发出的signal信号,由receiver的slot函数处理

而disconnect是将sender发出的signael信号,和receive的slot函数取消关联关系

六. lambda表达式的槽函数

槽函数也可以使用lambda表达式简化编写,不需要像传统的槽函数那样声明定义。

Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);     QPushButton *button = new QPushButton(this);     button->setText("QDebug打印输出");     button->move(250, 250);      connect(button, &QPushButton::clicked, this, [](){        qDebug() << "lambda表达式的槽函数";     }); }

注意lambda表达式的参数同样遵循上述规则——参数个数小于等于信号的参数个数

同时,lambda表达式捕获参数建议值捕获,因为在函数中一般控件对象使用指针管理,但因为挂接对象树的原因,出了函数控件对象并没有销毁,但指针是不可用的,所以在lambda表达式中捕获参数建议使用值捕获

相关内容

热门资讯

第三方插件!即赢互动辅助透视挂... 第三方插件!即赢互动辅助透视挂,闽游麻将是真的有挂,竟然有挂教程1、许多玩家不知道闽游麻将辅助怎么退...
推荐攻略!AAPoKer辅助挂... 推荐攻略!AAPoKer辅助挂多功能透视工具,其实有挂(有挂神器)1、AAPoKer公共底牌简单,A...
随着!红中麻将辅助透视挂,打两... 随着!红中麻将辅助透视挂,打两圈兴化麻将真的是有挂,其实有挂解密进入游戏-大厅左侧-新手福利-激活码...
玩家必看攻略!aapoker辅... 玩家必看攻略!aapoker辅助挂多功能透视工具,竟然真的是有挂(确实有挂)1、首先打开aapoke...
目前!天龙八部辅助透视挂,趣玩... 目前!天龙八部辅助透视挂,趣玩贵州麻将是真的有挂,都是证实有挂1、玩家可以在天龙八部线上大神俱乐部对...
今日焦点!wpk辅助挂多功能透... 今日焦点!wpk辅助挂多功能透视工具,确实真的有挂(有挂分享)wpk辅助器是一种具有地方特色的麻将游...
据公告内容!多彩世界辅助透视挂... 据公告内容!多彩世界辅助透视挂,天天监利麻将是有挂,好像有挂规律1、每一步都需要思考,不同水平的挑战...
新手必备!AAPoKer辅助挂... 新手必备!AAPoKer辅助挂多功能透视工具,其实是有挂(有挂技巧)1、首先打开AAPoKer辅助器...
最终!8522TV辅助透视挂,... 最终!8522TV辅助透视挂,福气棋牌真的有挂,切实有挂方略亲,关键说明,福气透视脚本安卓赛季回归,...
分辨真假!wepoker辅助挂... 分辨真假!wepoker辅助挂多功能透视工具,一贯真的有挂(有挂秘籍)1、这是跨平台的wepoker...