【Qt】信号与槽

avatar
作者
猴君
阅读量:1

目录

一. 什么是信号/槽 

二. 连接信号与槽

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 <QWidget>  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表达式中捕获参数建议使用值捕获

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!