ToB企服应用市场:ToB评测及商务社交产业平台

标题: C++ Qt开发:如何使用信号与槽 [打印本页]

作者: 海哥    时间: 2024-2-12 07:44
标题: C++ Qt开发:如何使用信号与槽
在Qt中,信号与槽(Signal and Slot)是一种用于对象之间通信的机制。是Qt框架引以为傲的一项机制,它带来了许多优势,使得Qt成为一个强大且灵活的开发框架之一。信号与槽的关联通过QObject::connect函数完成。这样的机制使得对象能够以一种灵活而松散耦合的方式进行通信,使得组件之间的交互更加灵活和可维护。
信号(Signal)是一种特殊的成员函数,用于表示某个事件的发生。当特定的事件发生时,对象会发射(emit)相应的信号。例如,按钮被点击、定时器时间到达等都可以是信号。
槽(Slot)是用于处理信号的成员函数。槽函数定义了在特定信号发生时执行的操作。一个槽可以与一个或多个信号关联,当信号被发射时,与之关联的槽函数将被调用。
在早期,对象间的通信采用回调实现。回调实际上是利用函数指针来实现,当我们希望某件事发生时处理函数能够获得通知,就需要将回调函数的指针传递给处理函数,这样处理函数就会在合适的时候调用回调函数。回调有两个明显的缺点:
而信号与槽机制则可以更好的比秒上述问题的产生,以下是信号与槽机制的一些优势:
总体而言,这些优势使得Qt成为构建各种类型应用程序的理想选择。
1.1 信号与槽函数

1.1.1 Connect

信号和槽进行关联使用的是QObject类的connect()函数,QObject::connect 是用于建立信号与槽连接的Qt框架函数。它有几个不同的重载形式,但最常用的形式是:
  1. static QMetaObject::Connection QObject::connect(
  2.     const QObject *sender,
  3.     const char *signal,
  4.     const QObject *receiver,
  5.     const char *slot,
  6.     Qt::ConnectionType type = Qt::AutoConnection
  7. );
复制代码
参数解释如下:
在函数定义中,第一个参数sender为发送信号的对象,第二个参数signal为要发送的信号,第三个参数receiver为接收信号的对象,第4个参数slot为接收对象在接收到信号之后所需要调用的槽函数。该函数的最后一个参数表明了关联的方式,默认值是Qt::AutoConnection方式,函数最终返回值是一个 QMetaObject::Connection 对象,可以用于断开连接时使用。
这个函数的作用是将 sender 对象的 signal 与 receiver 对象的 slot 进行连接。当 sender 发出信号时,receiver 对象的 slot 函数将被调用。
1.1.2 Disconnect

QObject::disconnect 是 Qt 框架用于断开信号与槽连接的函数。它有几个不同的重载形式,但最常用的形式是:
  1. static bool QObject::disconnect(
  2.     const QObject *sender,
  3.     const char *signal,
  4.     const QObject *receiver,
  5.     const char *slot
  6. );
复制代码
参数解释如下:
这个函数的作用是断开 sender 对象的 signal 与 receiver 对象的 slot 之间的连接。如果连接存在,那么它将被断开,不再触发。该函数返回值是一个 bool 类型,表示是否成功断开连接。
1.2 应用信号与槽

1.2.1 信号与槽绑定

信号与槽函数的使用非常容易理解,笔者将以最简单的案例来告诉大家该如何灵活的运用这两者,首先新建一个Qt Widgets Application项目,如下图所示第一个则是该项目的选项卡,其他参数保持默认即可;

当项目被创建好之后读者应该能构建看到如下图所示的页面提示信息,其中的untitled.pro是项目的主配置文件该配置文件一般有Qt自动维护,文件夹Headers则是项目的头文件包含路径,Sources则是代码的实现路径,最后一个Forms是用于图形化设计的UI模板。

首先双击mainwindow.ui进入到UI设计模式,接着拖拽一个PushButton按钮组件,与两个lineEdit组件到右侧的窗体画布上,并按下Ctrl+S保存该画布,刷新配置文件,如下图所示;

此时回到编辑菜单,并点击mainwindow.h头文件部分,并在头文件mainwindow.h的类MainWindow的定义中声明槽函数,代码如下,其含义是定义一个按钮点击槽:
  1. public slots:
  2.     void on_pushButton_clicked();
复制代码

接着我们就需要点击mainwindow.cpp文件,并在头文件中实现这个槽函数的具体功能,此处我们就实现设置两个lineEdit组件分别用于显示两串字符串,代码如下;
  1. void MainWindow::on_pushButton_clicked()
  2. {
  3.     ui->lineEdit->setText("hello lyshark");
  4.     ui->lineEdit_2->setText("www.lyshark.com");
  5. }
复制代码

最后一步则是建立映射关系,在类MainWindow的构造函数中添加如下语句,以便将信号和槽函数进行连接:
  1. #include "mainwindow.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent)    : QMainWindow(parent)    , ui(new Ui::MainWindow){    ui->setupUi(this);    // 建立关联当点击pushButton时信号clicked 发送给槽on_pushButton_clicked    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_pushButton_clicked));}MainWindow::~MainWindow(){    delete ui;}void MainWindow::on_pushButton_clicked()
  2. {
  3.     ui->lineEdit->setText("hello lyshark");
  4.     ui->lineEdit_2->setText("www.lyshark.com");
  5. }
复制代码
此时运行程序,当读者点击按钮时,则会自动触发on_pushButton_clicked()所关联的代码,将两个lineEdit设置为不同的内容,如下图;

当然了,上述过程都是需要我们手动的去关联信号与槽,在开发中其实可以直接在PushButton组件上邮件,选中转到槽选项,此时则会弹出关于该组件所支持的所有槽函数,读者只需要选中并双击,即可自动实现槽函数的创建与管理,这对于高效率开发是至关重要的。

当然在槽函数使用结束后我们需要断开,在断开时直接使用disconnect并传入需要断开的绑定sender信号即可,如下所示;
  1. void MainWindow::on_pushButton_2_clicked()
  2. {
  3.     disconnect(ui->pushButton,SIGNAL(clicked()),nullptr,nullptr);
  4. }
复制代码
1.2.2 匿名函数绑定

你是否感觉使用代码创建信号与槽很麻烦呢,其实通过使用Lambda表达式我们可以与Connect完美的结合在一起使用,者能够让信号与槽的使用更加的得心应手。
Lambda表达式是一种匿名函数的表示方式,引入C++11标准,用于创建内联函数或闭包。Lambda表达式可以在需要函数对象的地方提供一种更为简洁和灵活的语法。
它的基本形式如下:
  1. [capture](parameters) -> return_type {
  2.     // 函数体
  3. }
复制代码
使用Lambda表达式与Qt的connect函数结合实现匿名槽函数。具体概述如下:
Lambda表达式的初始化
  1. [=]() {
  2.     this->setWindowTitle("初始化..");
  3. }();
复制代码
这里使用Lambda表达式对 this->setWindowTitle("初始化.."); 进行了初始化,Lambda表达式中的 [=] 表示捕获外部变量并通过值传递,其中的 () 表示Lambda表达式立即执行,实现对窗口标题的初始化。
Lambda表达式作为槽函数
[code]connect(btn_ptr1, &QPushButton::clicked, this, [=]() mutable {    number = number + 100;    std::cout




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4