Qt中connect()函数及用法详解

 更新时间:2024年07月11日 11:42:03   作者:涩即是Null  
connect() 函数就是Qt 框架中用于将信号(SIGNAL)和槽(SLOT)关联起来的核心函数,本文给大家介绍Qt中connect()函数,感兴趣的朋友跟随小编一起看看吧

一、基本概念

        要想了解connect() 函数,要先知道在Qt中什么是什么是信号(SIGNAL)和槽(SLOT)。

        信号(SIGNAL):指在特定情况下发射的通知。比如当我们点击了用户界面的一个按钮之后就发射了一个信号。

        槽(SLOT):是指对信号进行响应的函数。也就是我们点击了一个按钮后我们要实现的功能。

        那么connect() 函数就是Qt 框架中用于将信号(SIGNAL)和槽(SLOT)关联起来的核心函数。

二、用法

1.旧版用法(Qt4和早期Qt5)

connect(sender, SIGNAL(signalName()), receiver, SLOT(slotName()));
  • sender:发射信号的对象名称
  • signalName():信号名称
  • receiver:接收信号的对象名称,一般情况下为槽函数所属对象,写this即可
  • slotName():槽函数名称

示例: 

connect(button, SIGNAL(clicked()), this, SLOT(handleButtonClicked()));

注意: 如果信号与槽函数带参数还需要在函数括号内标出。

2.新版用法(推荐)

connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);

         这里引入了基于函数指针的语法,使得编译器可以进行更好的类型检查。但是这里有一个问题:与旧版的写法不同的是,信号与槽函数的参数怎么办?

        首先我们知道,在 Qt 的信号与槽机制中,槽函数的参数不能多于信号的参数。也就是说,信号的参数可以多于槽的参数,且槽函数的参数必须是信号参数的一个子集。那么就可以分为如下三种情况:

        1.信号和槽函数具有相同数量和类型的参数。这时可以直接连接且无需出现函数参数:

connect(lineEdit, &QLineEdit::textChanged, this, &Widget::do_textChanged);

在上面示例中,信号textChanged(QString)和槽函数do_textChanged(QString)参数相同。

        2.信号的参数多于槽函数的参数。槽函数将忽略信号的多余参数,这个特性允许你在信号和槽参数不完全匹配的情况下,仍然能够正常工作。正常情况下,不推荐把槽函数设计为overload型。

        3.某些信号的参数有默认值。也就是说同一信号的参数分为有参数和无参数,如QCheckBox的clicked()信号和clicked(bool)信号。这时connect()函数有两种写法:

                a.设置不同名字的槽函数: 

//槽函数
void do_checked(bool checked);
void do_checked_NoParam();
//connect()函数
connect(checkBox, &QCheckBox::clicked, this, &Widget::do_checked);
connect(checkBox, &QCheckBox::clicked, this, &Widget::do_checked_NoParam);

                b.使用模板函数qOverload()来明确参数类型:

connect(checkBox, &QCheckBox::clicked, this, qOverload<bool>(&Widget::do_checked));
connect(checkBox, &QCheckBox::clicked, this, qOverload<>(&Widget::do_checked));

3.自动连接(无需使用connect()函数)

        在构建项目时,若勾选了“Generate form”字段,则会生成一个后缀为“.ui”的文件。

        那么在ui设计界面种可以选中一个对象,右键选择“Go to slot”或者“转到槽”,在弹出的对话框中再选择信号,那么就会自动生成一个槽函数。如果槽函数的名称符合相应的格式,Qt 会在运行时通过setupUi(this)自动生成connect()函数完成连接。

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
{
    //由go to slot生成的槽函数可以自动关联
    ui->setupUi(this);  
    //自定义槽函数需要手动关联
    connect(ui->radioButtonBlack,SIGNAL(clicked()),this,SLOT(do_setFontColor()));
}
//自动生成的槽函数格式:void on_<objectName>_<signalName>(){}
void Widget::on_btnCal_clicked()
{
    ...
}
//手动写的槽函数
void Widget::do_setFontColor()
{
    ...
}

        当然在设计一些复杂功能时,自动连接方法就不太适用了。

4.Lambda表达式(Qt5.4)

        lambda 表达式提供了一种非常灵活的方式来处理信号。有如下几个优点:

  • 可以直接在连接语句中定义信号处理逻辑,无需在类中定义额外的槽函数。这在处理简单逻辑时尤其方便。
  • 避免为每个信号处理逻辑定义新的槽函数,减少命名空间污染。
  • 允许你在处理信号参数时,捕获外部变量或定义额外的处理逻辑。

基本格式如下:

connect(sender, &SenderClass::signalName, [lambda expression]);

         举个栗子对比理解一下:

//方法一:使用槽函数指针连接
void processData(int value, QString message) {
    if (value > 10) {
        qDebug() << "Value is greater than 10:" << value << ", Message:" << message;
    } else {
        qDebug() << "Value is 10 or less:" << value;
    }
}
QObject::connect(&sender, &SenderClass::signalName, this, &ReceiverClass::processData);
//方法二:使用lambda表达式连接
QObject::connect(&sender, &SenderClass::signalName, [this](int value, QString message) {
    if (value > 10) {
        qDebug() << "Value is greater than 10:" << value << ", Message:" << message;
    } else {
        qDebug() << "Value is 10 or less:" << value;
    }
});

三、断开连接disconnect()

1.为什么使用disconnect()

        使用connect()函数可以关联信号与槽,那么删除connect()函数不就可以断开连接了吗?

         其实不然!我们最好使用官方的 disconnect() 函数来解除信号与槽的连接。原因有如下几点:

a.动态控制信号和槽的连接

        有时你需要在运行时动态地控制信号和槽的连接。例如,你可能需要在某些情况下连接信号和槽,而在其他情况下断开它们。在这种情况下,使用 disconnect() 函数可以让你在需要时灵活地断开连接,而不需要修改代码来删除 connect() 调用。

b.保持代码的结构和可读性

         connect() 调用通常在类的构造函数或初始化方法中设置,表示对象之间的关系和交互。将连接和断开连接的逻辑分开可以使代码更清晰、更具结构性。如果直接删除 connect() 调用,代码逻辑可能会变得混乱且难以维护。

c. 方便的调试和维护

        使用 disconnect() 可以更方便地调试和维护代码。你可以在调试时临时断开某些连接,而无需删除和重新添加 connect() 调用。这样可以避免错误,并更容易地还原代码。

d. 多次连接和断开

        在某些情况下,你可能会多次连接和断开相同的信号和槽。例如,当某个条件发生变化时,你希望断开以前的连接并建立新的连接。使用 disconnect() 可以确保你正确地断开之前的连接,而不会遗留下不需要的连接。

2.使用方法

a.解除与一个发射者所有信号的连接

disconnect(myObject, nullptr, nullptr, nullptr);
myObject->disconnect();

b.解除与一个特定信号的所有连接

disconnect(myObject, SIGNAL(mySignal), nullptr, nullptr);
myObject->disconnect(SIGNAL(mySignal));

c.解除与一个特定接收者的所有连接

disconnect(myObject, nullptr, myReceiver, nullptr);
myObject->disconnect( myReceiver);

d.解除特定的一个信号与槽的连接

disconnect(lineEdit, &QLineEdit::textChanged, label, &QLabel::setText);

四、细节问题

        1. 一个信号可以连接到多个槽,所有连接的槽都会在信号发出时依次被调用。

connect(sender, &SenderClass::signalName, receiver1, &ReceiverClass1::slotName);
connect(sender, &SenderClass::signalName, receiver2, &ReceiverClass2::slotName);

        2. 信号和槽机制是单向的,即信号发出时会调用槽函数,但槽函数中发出的信号不会自动调用其他槽函数,除非你明确连接了这些信号和槽。

到此这篇关于Qt中connect()函数的文章就介绍到这了,更多相关Qt connect()函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言中函数指针的三种使用方法总结

    C语言中函数指针的三种使用方法总结

    这篇文章主要介绍了 C语言中函数指针的三种使用方法总结的相关资料,希望通过本文大家能够彻底掌握指针的使用方法,需要的朋友可以参考下
    2017-10-10
  • 如何在 clion 运行多个 main 函数(方法详解)

    如何在 clion 运行多个 main 函数(方法详解)

    这篇文章主要介绍了如何在 clion 运行多个 main 函数,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • C语言库函数qsort及bsearch快速排序算法使用解析

    C语言库函数qsort及bsearch快速排序算法使用解析

    这篇文章主要为大家介绍了C语言库函数qsort及bsearch快速排序算法的使用示例解析
    2022-02-02
  • C++函数重载的深入解析

    C++函数重载的深入解析

    在C++中,我们也能够把具有相同功能的函数整合到一个函数上,而不必去写好多个函数名不同的函数,这叫做函数的重载。以下是对C++中的函数重载进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-07-07
  • C++中全局变量的初始化全过程

    C++中全局变量的初始化全过程

    这篇文章主要介绍了C++全局变量的初始化全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • C++如何获取本机的IP地址

    C++如何获取本机的IP地址

    这篇文章主要为大家详细介绍了C++如何获取本机IP地址小程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • 详解C语言fscanf函数读取文件教程及源码

    详解C语言fscanf函数读取文件教程及源码

    这篇文章主要为大家介绍了详解C语言算法fscanf读取文件示例教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • 基于C++编写一个密码系统

    基于C++编写一个密码系统

    这篇文章主要为大家详细介绍了如何基于C++编写一个简单的密码系统,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-11-11
  • C语言超详细讲解字符串相乘

    C语言超详细讲解字符串相乘

    这篇文章主要介绍了用C语言如何来实现字符串相乘的方法,这里我们会利用到memset函数,memset函数是对较大的结构体或数组进行清零操作的一种最快方法,可以说是初始化内存的“万能函数”,下面我们详细了解一下
    2022-03-03
  • C++读取WAV音频文件的头部数据的实现方法

    C++读取WAV音频文件的头部数据的实现方法

    这篇文章主要介绍了C++读取WAV音频文件的头部数据的实现方法的相关资料,希望通过本文能帮助到大家,让大家实现这样的方法,需要的朋友可以参考下
    2017-10-10

最新评论