Qt——信号槽

信号和槽(slot)

类似于OS中的信号回调机制,一旦发射了信号就会触发(执行)槽函数**。在Qt中,信号看起来是函数的样子(之所以说看起来像,是因为实际上Qt暴露给我们的信号或者我们在Qt上自己创建的信号,都会被Qt的MOC处理成另外一种样子),而槽本质上就是一个函数。**

大部分信号都是Qt提供给我们的,但是我们也可以自定义信号。Qt也提供一些槽,但我们经常自己定义槽。对于Qt给我我们的,我们要多去查阅文档,从子类到父类向上寻找

在Qt中,信号和槽的关系是多对多关系,即一个槽可以被多个信号关联,一个信号可以关联多个槽。作为Qt的使用者,我们主要做的就是将信号源,信号,槽,接受对象关联起来,目的是使得用户操作后得到反馈。当信号源发射后信号后就会查找信号和槽的关联关系,执行与之关联的所有槽。


关联信号和槽

关联信号和槽有多种方式,我们下面逐一介绍

Connect函数方式

connect是QObject类(也就是Qt中所有类的祖宗)中的一个静态方法,因此所有类中都可以直接调用它。它常使用(connect有多个重载)的重载形式如下:

cpp 复制代码
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                                     const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
                                     Qt::ConnectionType type = Qt::AutoConnection)
  • sender:发送信号的控件对象的地址,即设置信号源。
  • signal:要关联的信号,以函数地址的方式传入。
  • receiver:要对信号做出反应的控件对象,以对象指针的方式传入。
  • slot:槽函数,以函数指针的方式传入。
  • type:基本不会用到,暂时不做解释

接下来我们来使用connect:

cpp 复制代码
/*只要点击按钮,按钮上就会出现"哈哈"*/

void Widget::handler()
{
    button->setText("哈哈");
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    button = new QPushButton(this);//创建按钮对象,button是widget的成员属性
    button->move(100,100);//将button安置到某位置

    //建立关联关系,&QPushButton::clicked是QAbstractButton的给我们提供的信号,
    //继承这个类的其他类型的按钮也有这个信号
    connect(button,&QPushButton::clicked,this,&Widget::handler);//建立关联关系
}
cpp 复制代码
/*只要点击按钮,窗口就会关闭*/

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    button = new QPushButton(this);//创建按钮对象,button是widget的成员属性
    button->move(100,100);//将button安置到某位置

    //建立关联关系,&QPushButton::clicked是QAbstractButton的给我们提供的信号,
    //继承这个类的其他类型的按钮也有这个信号
    //&Widget::close是widget提供给我们的槽
    connect(button,&QPushButton::clicked,this,&Widget::close);//建立关联关系
}

顺便提一下,以前connect函数的第二和第四个参数都是char*类型的,因此每次传参都要把实参用宏强转成char*,但是现在重载了更好用的版本。

自动关联方式

右击选中想要设置信号和槽的控件,然后选择'转到槽':

然后我们选择一个按钮发射的信号:

然后我们发现widget的成员函数多了一个(头文件和源文件都写好了):

接下来我么只要在该函数编写信号的处理过程即可,该函数就是pushbutton按钮发出发射信号后所执行的槽函数。并且我们不需要手动关联信号源,信号,接收对象,槽,而是Qt通过命名方式自动关联的:

接下来我们使用一下这种方式:

cpp 复制代码
/*点击按钮,按钮上出现"哈哈"*/

void Widget::handler()
{
    button->setText("哈哈");
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

}

Widget::~Widget()
{
    delete ui;
}
void Widget::on_pushButton_clicked()
{
    ui->pushButton->setText("哈哈");
}

当我们查看ui文件生成的类,可以发现:

这个函数就是开启名字匹配的方式。


disconnect解除关联

diconnect函数和connect用法一样,只不过他是把关联关系解除


自定义槽

上面已经使用过自定义槽和Qt提供的槽(如close)。自定义槽其实就是编写一个成员函数然后传参给connect即可,但是在早期,Qt中自定义槽需要在声明时加**"slot"关键字****来帮助Qt进行元编程(现在不需要了,但是加上也可以),比如下面这样:**

槽还可以是一个lambda表达式,调用connect的时候传入即可**:**

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
     ui->setupUi(this);
     button = new QPushButton(this);
     connect(button,&QPushButton::clicked,this,[this]()->void{this->setWindowTitle("haha");});
}
Widget::~Widget()
{
    delete ui;
}

自定义信号

自定义信号只需要写出函数声明,并告诉Qt这是一个信号(使用signals关键字)即可,但是要保证信号的返回值必须是void。例如这样:

定义信号过后,就可以像正常信号一样关联使用了:

上面程序的意思就是打开窗口后Widget发送信号,然后将Widget内的按钮文本替换成"哈哈"。emit也是Qt添加的关键字,表示发射一个信号,但实际上现在不加emit也可以。


信号和槽的参数

如果要使用参数,信号和槽的对应参数的类型必须一致,但是在个数上信号的参数可以比槽更多(不可以更少),这样可以让槽被更多信号复用,关联。直接举一个使用参数的例子:

在这个例子中,我们实现了按不同按钮就设置不同标题的功能,但是设置标题的槽函数只有一个。


注意

一个类想要定义信号和槽,必须在类声明最开始的地方,写下Q_OBJECT宏:

如果不写这个宏,那么不能定义信号槽,但是使用Qt库提供给我们的信号槽是可以的

相关推荐
Echo缘5 小时前
嵌入式系统C语言资源分类与内存分布分析
c语言·开发语言
imatt5 小时前
Qt Creator 在Windows下编译信息乱码
windows·qt
JaneConan5 小时前
鸿蒙 ArkUI 深水区:@Watch 和 @Observed,状态变了「自动跑」+ 嵌套对象「深层重绘」
开发语言·后端·ui·harmonyos
赤水无泪5 小时前
qt中图标、名称的设置方式
开发语言·qt
王莎莎-MinerU5 小时前
MCP 解决的是工具接入,科研 Agent 还缺的是科学证据接口标准化
开发语言·网络·人工智能·深度学习·pdf·c#·php
橘子海全栈攻城狮6 小时前
【最新源码】基于SpringBoot + Vue的超市管理系统的设计与实现D002
java·开发语言·vue.js·spring boot·后端·spring
在水一缸6 小时前
深入浅出 Catch2:现代 C++ 测试框架的优雅实践
开发语言·c++·单元测试·log4j·测试框架·catch2
-银雾鸢尾-6 小时前
C#中Object类内的方法
开发语言·c#
浮江雾6 小时前
Flutter第十节-----Flutter布局与组件全解析
android·开发语言·前端·学习·flutter·入门
爱喝水的鱼丶6 小时前
SAP-ABAP:ALV跨版本兼容指南——适配ECC与S4 HANA系统的ALV开发注意事项
开发语言·性能优化·sap·abap·经验交流