【Qt】信号与槽

目录

一. 什么是信号/槽 

二. 连接信号与槽

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

相关推荐

  1. qt-信号

    2024-07-13 14:48:03       27 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 14:48:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 14:48:03       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 14:48:03       58 阅读
  4. Python语言-面向对象

    2024-07-13 14:48:03       69 阅读

热门阅读

  1. go-基准测试

    2024-07-13 14:48:03       24 阅读
  2. kafka部署以及常用命令详细总结

    2024-07-13 14:48:03       18 阅读
  3. windows安全加固

    2024-07-13 14:48:03       19 阅读
  4. 微服务架构实战:案例分析与解决方案探讨

    2024-07-13 14:48:03       22 阅读
  5. 【数据结构】B树

    2024-07-13 14:48:03       18 阅读
  6. kafka 常用命令

    2024-07-13 14:48:03       22 阅读
  7. 解压zip、tar、gz文件--linux003

    2024-07-13 14:48:03       16 阅读
  8. Python调用摄像头

    2024-07-13 14:48:03       22 阅读