QT中信号和槽机制

信号和槽机制

QT提供了信号和槽机制用于完成界面操作的响应,信号和槽是用来完成任意两个QT对象之间的通信机制。

信号和槽机制的连接方式

信号和槽函数之间需要通过connect函数进行连接 Qt中connect函数的基本语法:

cpp 复制代码
connect(发送者, 发送的信号, 接收者, 槽函数);
  • 发送者:发射信号的对象。
  • 发送的信号:信号函数的地址
  • 接收者:具有槽函数来处理信号的对象。
  • 槽函数:指定槽函数地址

示例: 创建一个按钮,点击按钮关闭窗口

首先在主窗口构造函数中实现代码如下:

cpp 复制代码
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //新建按钮
    QPushButton* btn =new  QPushButton("按钮",this);
    
    //连接信号和槽clicked是QT库提供的,close是QWidget中的槽函数都是库提供的,QMainWindow继承了QWidget,所以也能直接用
    connect(btn,&QPushButton::clicked,this,&QMainWindow::close);

}

MainWindow::~MainWindow()
{
    delete ui;
}

运行结果

QT自定义信号和槽

通过自定义信号和槽,可以在应用程序中实现自己的事件处理机制。

自定义信号

  • 自定义的信号需要写的类中signal访问限定符下
  • 返回值是void
  • 自定义的信号只需要声明不需要实现。
  • 自定义的信号可以有参数,即支持重载
  • 触发信号需要使用关键字emit

自定义槽函数

  • 自定义的槽函数需要声明且需要实现
  • 可以写到public,或者public slot访问限定符下,或者写为全局函数。(一般建议写到public slot下,新老版本的qt都支持,写到piblic下只有新版本支持)
  • 槽函数也可以有参数,也支持重载,信号和槽函数的参数类型必须一一对应
  • 信号的参数可以多于槽函数的参数个数

示例

比如实现一个场景,老师下课后触发饿了的信号,学生接收信号请老师吃饭

在teacher类中声明信号

cpp 复制代码
//teacher.h
#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals:
    //自定义信号只需要声明  不需要实现
    //返回值是void
    void signa();
};

#endif // TEACHER_H

再student类中声明槽函数

cpp 复制代码
//satudent.h
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
    //自定义槽函数,需要声明且实现
    void slot();

signals:
};
#endif // STUDENT_H

实现Student中slot函数

cpp 复制代码
//student.cpp
#include "student.h"
#include <QDebug>
Student::Student(QObject *parent)
    : QObject{parent}
{}
void Student::slot()
{
    qDebug() << "Invite the teacher to dinner";//请老师吃饭
}

在窗口类中声明一个下课后的函数

cpp 复制代码
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "teacher.h"
#include "student.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void trigger();//下课后触发信号

private:
    Ui::MainWindow *ui;
    Teacher* _t1;
    Student* _s1;
};
#endif // MAINWINDOW_H

实现下课后,触发老师饿了的信号,触发之前连接信号和槽函数

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

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    _t1 = new Teacher(this);
    _s1 = new Student(this);

    //连接信号和槽
    //connect参数1 信号发送者,参数2 发送的信号
    //       参数3 信号的接收者 参数4 槽函数
    connect(_t1,&Teacher::signa,_s1,&Student::slot);

    trigger();

}
//实现下课后触发老师饿了的信号
void MainWindow::trigger()
{
    //触发信号关键字
    emit _t1->signa();
}

MainWindow::~MainWindow()
{
    delete ui;
}

运行结果:

成功的请老师吃饭了(吃赛博晚饭)。成功的连接到了自定义的信号和槽

对上面进行改进,添加一个按钮,点击按钮,触发信号

cpp 复制代码
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    _t1 = new Teacher();
    _s1 = new Student();
    //添加按钮
    QPushButton* _btn = new QPushButton("按钮",this);
    resize(600,400);
    //连接信号和槽
    //connect参数1 信号发送者,参数2 发送的信号
    //       参数3 信号的接收者 参数4 槽函数
    connect(_t1,&Teacher::signa,_s1,&Student::slot);
    //点击按钮,触发信号
    connect(_btn,&QPushButton::clicked,this,&MainWindow::trigger);
}
void MainWindow::trigger()
{
    //触发信号关键字
    emit _t1->signa();
}

MainWindow::~MainWindow()
{
    delete ui;
}

运行结果

自定义信号和槽函数发生重载

connewct连接信号和槽函数时,参数需要传函数得地址,当发生重载时需要利用函数指针明确函数的地址

Teacher类中声明信号

cpp 复制代码
 void signa();
 void signa(QString str);

两个singa构成重载

在Student类中声明并实现槽函数

cpp 复制代码
//student.h
    void slot();
    void slot(QString str);
cpp 复制代码
//student.cpp
void Student::slot()
{
    qDebug() << "Invite the teacher to dinner";
}
void Student::slot(QString str)
{
    qDebug() << "Invite the teacher to dinner,eat:" << str;
}

窗口类中实现功能

cpp 复制代码
//信号和槽函数发生重载时,需要用函数指确定函数的地址
void (Teacher::*signaadder1)()= &Teacher::signa;//无参信号地址
void (Teacher::*signaadder2)(QString)= &Teacher::signa;//有参信号地址

void (Student::*slotadder1)() = &Student::slot;//无参槽函数地址
void (Student::*slotadder2)(QString) = &Student::slot;//有参槽函数地址
//连接信号和槽函数
connect(_t1,signaadder2,_s1,slotadder2);
//通过按钮点击触发信号
connect(_btn,&QPushButton::clicked,this,&MainWindow::trigger);

运行结果:

成功调用了有参版本的槽函数。

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