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);

运行结果:

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

相关推荐
蓝祁子yoky16 小时前
Qt学习日记 Day13:网络编程(一)-TCP基础与Socket实战
网络·qt·学习
飞浪纪元[FWC–FE]19 小时前
从零到一键绿:Qt 5.14.2 + VS2019 开发环境搭建、Kit 套件配置与构建错误修复完全手册
开发语言·qt
ShineWinsu20 小时前
对于Qt:QCheckBox常见属性的详细解析
c++·qt·面试·笔试·gui·qcheckbox·多选框
ShineWinsu1 天前
对于Qt:QPushButton常见属性的解析
开发语言·c++·qt·api·gui·按钮·qpushbutton
飞浪纪元[FWC–FE]1 天前
Qt 工程创建与 CMake / qmake 构建规范
开发语言·数据库·qt
Lhan.zzZ1 天前
用 Qt 构建线程安全的通讯静态库:从线程亲和性到完整工程
c++·vscode·qt·tcp/ip·udp
飞浪纪元[FWC–FE]1 天前
Qt 构建排错实录:从 MSB 1009 到生成器选型
开发语言·数据库·qt
小徐不徐说1 天前
C++ 接口与插件设计:从工厂注册到 Qt 动态插件
数据库·c++·qt·系统架构·程序设计
小王C语言1 天前
Qt常用控件:容器类控件,标题分组框、标签页(浏览器标签)
开发语言·qt
TMedical1 天前
MedPlanning 截骨模拟矫形功能
c++·图像处理·人工智能·qt·健康医疗