Qt教程 — 2.2 深入了解Qt信号与槽

目录

[1 信号与槽简介](#1 信号与槽简介)

[2 如何在UI 文件里连接信号与槽](#2 如何在UI 文件里连接信号与槽)

[3 Qt 信号与槽机制](#3 Qt 信号与槽机制)

[3.1 QObject::connect() 信号与槽实现函数](#3.1 QObject::connect() 信号与槽实现函数)

[方式一:通过UI Designer会自动生成QObject::connect()](#方式一:通过UI Designer会自动生成QObject::connect())

方式二:手动方式编辑QObject::connect()

[3.2 信号与槽的注意事项](#3.2 信号与槽的注意事项)

[(1) 一个信号可以连接多个槽](#(1) 一个信号可以连接多个槽)

[(2) 多个信号可以连接同一个槽](#(2) 多个信号可以连接同一个槽)

[(3) 一个信号可以连接另外一个信号](#(3) 一个信号可以连接另外一个信号)

[(4) 断开一切与 myObject 连接的信号或槽](#(4) 断开一切与 myObject 连接的信号或槽)

[(5) 断开所有连接到特定信号的东西](#(5) 断开所有连接到特定信号的东西)

[(6) 与指定的接收者断开连接](#(6) 与指定的接收者断开连接)

[4 如何在项目中创建信号和槽](#4 如何在项目中创建信号和槽)

[4.1 如何在项目里创建信号](#4.1 如何在项目里创建信号)

[4.2 如何在项目里创建槽](#4.2 如何在项目里创建槽)

[4.3 如何在项目中连接信号与槽](#4.3 如何在项目中连接信号与槽)


1 信号与槽简介

Qt的信号与槽机制是Qt框架中实现对象之间通信的一种方式,属于Qt的核心特性之一。在这个机制中,信号(signal)是由对象在发生了某种状态改变时发出的消息,槽(slot)是用来被信号触发的函数。

  • **信号(Signal):**是由对象发出的一种特殊的公共成员函数,但它不是由程序员直接调用的,而是由Qt自己调用以响应某个事件。信号一旦发生,就会通知那些与之连接的槽函数。
  • **槽(Slot):**可以是普通的成员函数,用于响应信号。槽可以与任何信号连接,而与信号发生的对象的类型无关。当与之相连的信号被触发时,槽函数就会被自动调用。

这种机制相比于传统的回调函数有很多优势,最主要的是它能够确保程序的松耦合和高级的事件处理能力。通过信号和槽,Qt开发者可以轻松地在不同的组件之间进行消息传递,从而使得应用程序架构更为清晰和灵活。

2 如何在UI 文件里连接信号与槽

在文章2.2节已进行了详细的描述:Qt教程 --- 2.1 如何使用Qt Designer 开发UI程序-CSDN博客

3 Qt 信号与槽机制

3.1 QObject::connect() 信号与槽实现函数

信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:

QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

  • **connect() :**是 QObject 类的一个静态函数,而 QObject 是所有 Qt 类的基类,在实际调用时可以省略前面的限定符。
  • sender: 是发射信号的对象的名称。
  • **signal():**是信号名称。信号可以看做是特殊的函数, 需要带括号,有参数时还需要指明参。
  • **receiver:**是接收信号的对象名称。
  • **slot() :**是槽函数的名称,需要带括号,有参数时还需要指明参数。
方式一:通过UI Designer会自动生成QObject::connect()

通过第2节的方法设置好通过按钮关闭主窗口的信号和槽后,运行后在mainwindow.app ---> ui_mainwindow.h头文件中会自动生成QObject::connect() 函数,修改程序内容ui_mainwindow.h头文件也会自动更新。

方式二:手动方式编辑QObject::connect()

在mainwindows.cpp下,直接将方式一生成的代码复制到会报错,原因是pushButton和this->MainWindows找不到位置,pushButton是命名空间ui下的成员函数,this->MainWindows就在MainWindows命名空间下,写成this即可,具体代码如下:

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // QObject::connect(pushButton, SIGNAL(clicked()), this->MainWindow, SLOT(close()));
    
    QObject::connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(close()));
    
}

代码修改位置如下:

3.2 信号与槽的注意事项

(1) 一个信号可以连接多个槽

当一个信号与多个槽函数关联时,槽函数按照建立连接时的顺序依次执行。

connect(pushButton, SIGNAL(clicked()), this, SLOT(hide());

connect(pushButton, SIGNAL(clicked()), this, SLOT(close());

这是当一个对象 pushButton 的被单击时,窗体有两个槽进行响应,一个 hide()用于隐藏主窗体,一个 close() 用于关闭主窗体。 这里只是举个例子,实际上当执行 close()后, hide()这个槽已经没有什么意义了, 因为已经程序退出了, 但是实际它有执行,因为它连接在 close()的前面。

(2) 多个信号可以连接同一个槽

多个信号可以连接同一个槽,例如设置3个pushButton 到设计的窗体里,同时也让它按3.1小节里的第一种方法连接信号与槽,把三个按钮的 clicked()信号对应连接到close()、hide()、lower()槽函数。

编译后可以在 ui_mainwindow.h 这个文件里自动生成如下的信号槽连接语句。

cpp 复制代码
QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close()));
QObject::connect(pushButton_2, SIGNAL(clicked()), MainWindow, SLOT(hide()));
QObject::connect(pushButton_3, SIGNAL(clicked()), MainWindow, SLOT(lower()));
(3) 一个信号可以连接另外一个信号

这样,当一个信号发射时,也会发射另外一个信号,实现某些特殊的功能。

connect(pushButton,SIGNAL(objectNameChanged(QString)),this,SIGNAL(windowTitelChanged(QString)));

  • pushButton 是信号的发送者,指的是一个按钮对象(假定是QPushButton类型的)。
  • SIGNAL(objectNameChanged(QString)) 是发送者发出的信号,这里指的是pushButtonobjectNameChanged信号,该信号在对象的objectName属性改变时发出。objectNameChanged(QString)传递一个QString参数,表示新的对象名称。
  • **this:**指的是信号的接收者,在这个上下文中,通常指的是包含这行代码的对象(可能是一个窗口或者其他Qt对象)。
  • SIGNAL(windowTitleChanged(QString)) 是接收者将要发出的信号。这意味着当pushButtonobjectName属性发生变化时,不是调用一个槽函数,而是直接发出了一个新的信号windowTitleChanged(QString),同样传递一个QString参数,这个信号需要在接收者这边定义。
(4) 断开一切与 myObject 连接的信号或槽

disconnect(myObject, 0, 0, 0);

(5) 断开所有连接到特定信号的东西

disconnect(myObject, SIGNAL(mySignal()), 0, 0);

(6) 与指定的接收者断开连接

disconnect(myObject, 0, myReceiver, 0);

4 如何在项目中创建信号和槽

4.1 如何在项目里创建信号

(1) 新建项目命名为 03_signal_slot_example, 同时取消勾选*ui 文件, 其他步骤不变。

(2) 由于信号只需声明, 无需定义。 所以我们只需要在 mianwindow.h 里声明信号即可。 代码如下,如下图黑色加粗部分代码就是创建的信号。这里创建一个 void pushButtonTextChanged();信号。完整代码如下:

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
signals:
    void PushButtonTextChanged();
};
#endif // MAINWINDOW_H

4.2 如何在项目里创建槽

创建槽的方法也很简单, 也是直接在 mianwindow.h 里直接声明槽,在 mianwindow.cpp 里

实现槽的定义,就是C++创建函数的流程。

槽有以下特点:

  • 槽可以是任何成员函数、普通全局函数、静态函数。
  • 槽函数和信号的参数和返回值要一致。

(1) 在mianwindow.h 声明信号 void pushButtonTextChanged();所以我们声明的槽函数必须是无返回值类型 void,和无需参数,同时还声明一个按钮点击的槽。此外还声明一个 QPushButton 对象 pushButton。完整代码如下:

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
// 引入 QPushButton文件
#include <QPushButton>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
signals:
    void PushButtonTextChanged();
    
public slots:
    // 声明一个槽函数
    void changeButtonText();
    // 声明按钮点击的槽函数
    void pushButtonClicked();

private:
    // 声明一个对象 pushButton
    QPushButton *pushButton;    
};
#endif // MAINWINDOW_H

(2) 在 mainwindow.cpp 里 实 现 声 明 的 槽 函 数 void changeButtonText(); 和 void pushButtonClicked(); 同时还实例化了 pushButton 对象。同时设置按钮的文字大小、边界和颜色参数。

4.3 如何在项目中连接信号与槽

在2.3节介绍了项目中连接信号与槽的函数。在 mainwindow.cpp 中补充信号槽连接的代码。 mainwindow.cpp完整代码如下:

cpp 复制代码
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 设置MainWindow尺寸
    this->resize(800,600);
    pushButton = new QPushButton(this);
    // 设置按钮文字
    pushButton->setText("我是一个按钮");
    // 设置按钮位置和尺寸
    pushButton->setGeometry(340, 50, 120, 60);
    // 设置按钮文字颜色
    pushButton->setStyleSheet("QPushButton { color: red; }");

    // 信号与槽连接
    connect(pushButton, SIGNAL(clicked()), this,SLOT(pushButtonClicked()));
    connect(this, SIGNAL(PushButtonTextChanged()), this, SLOT(changeButtonText()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::pushButtonClicked()
{
    emit PushButtonTextChanged();
}

void MainWindow::changeButtonText()
{
    pushButton->setText("被点击了");
    // 设置按钮文字颜色
    pushButton->setStyleSheet("QPushButton { color: green; }");
}

最后实现的效果如下,点击前文字为红色,点击后为绿色。

相关推荐
huanggang98216 分钟前
在Ubuntu22.04上使用Qt Creator开发ROS2项目
qt·ros2
老秦包你会42 分钟前
Qt第三课 ----------容器类控件
开发语言·qt
spygg2 小时前
Qt低版本多网卡组播bug
qt·组播·多网卡组播·qt5.7.0
码农客栈2 小时前
qt QWebSocketServer详解
qt
plmm烟酒僧4 小时前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
Black_Friend4 小时前
关于在VS中使用Qt不同版本报错的问题
开发语言·qt
CSUC4 小时前
【Qt】QTreeView 和 QStandardItemModel的关系
qt
冷凝女子5 小时前
【QT】海康视频及openCv抓拍正脸接口
qt·opencv·音视频·海康
苏三有春7 小时前
PyQt5实战——UTF-8编码器功能的实现(六)
开发语言·qt
Vanranrr8 小时前
C++ QT
java·c++·qt