欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > Qt信号和槽-->day04

Qt信号和槽-->day04

2025/2/25 2:58:22 来源:https://blog.csdn.net/m0_69093426/article/details/143655559  浏览:    关键词:Qt信号和槽-->day04

Qt信号和槽

  • 标准的信号和槽函数
    • Qt中的槽函数
    • Qt中的信号
  • connect
    • 案例
  • 自定义信号和槽
    • 案例分析
  • 信号槽的拓展
    • 信号连接信号案例
  • 信号槽的两种连接方式
    • Qt5中的处理方式
    • Qt4中的处理方式
    • Qt5处理信号槽重载问题
      • 案例
    • lambda表达式
      • 简单案例
      • Qt中的应用
  • 补充知识点
    • 关于lambda

标准的信号和槽函数

QWidget标准的信号和槽函数
在这里插入图片描述
此外信号和槽函数是可以被继承的
在这里插入图片描述
可以看到QPushButton是有标准的槽函数,但是没有看到信号。
实际上QPushButton是继承了它的父类的信号
在这里插入图片描述

Qt中的槽函数

Qt中的槽函数可以是类的成员函数、全局函数、静态函数、Lambda表达式(匿名函数)

Qt中的信号

信号需要使用 signals 关键字进行声明, 使用方法类似于public等关键字

connect

connect(信号发生者,信号,信号接受者,接受者的处理动作);

connect只是做了一个信号注册,具体操作步骤是通过qt框架进行实现的

案例

功能实现: 点击窗口上的按钮, 关闭窗口
功能分析:
- 按钮: 信号发出者 -> QPushButton 类型
- 窗口: 信号的接收者和处理者 -> QWidget 类型
在这里插入图片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
//  ui->closeBtn;//>>>>>>>>>>>>>>>>>>通过ui对象可以操纵所创建的按钮connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
}MainWindow::~MainWindow()
{delete ui;
}

不可以将第四个参数写为 &this->close,因为 &this->close 表示的是 MainWindow 类的成员函数指针,而 QPushButton::clicked 信号需要一个成员函数指针,而这个指针的类型是 void (MainWindow:😗)()(即没有参数且没有返回值的成员函数指针)。

自定义信号和槽

案例分析

假设要实现一个类GirlFriend发出hungry信号,一个类Me来接受信号进行处理。

  • 1、由于这两个是不同的类,所以应该提供一个窗口类对上面的这两个类进行包装
  • 2、在GirlFriend类中只需要声明信号,不需要实现,因为这是信号的发出者
  • 3、在Me类的槽函数不仅需要声明也需要实现

主窗口头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "girlfriend.h"
#include "me.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();public slots:void hungrySlot();private:Ui::MainWindow *ui;GirlFriend *g_girl;Me *m_me;
};
#endif // MAINWINDOW_H

主窗口函数实现

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
//  ui->closeBtn;//>>>>>>>>>>>>>>>>>>通过ui对象可以操纵所创建的按钮g_girl=new GirlFriend;m_me=new Me;//这个hungry是自定义的不由Qt框架提供,需要使用者发射信号 >>>>>>> 窗口中实现connect(g_girl,&GirlFriend::hungry,m_me,&Me::eat);//>>>>>>>>>>>>>>提醒Qt框架有信号connect(ui->hungry,&QPushButton::clicked,this,&MainWindow::hungrySlot);connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::hungrySlot()
{//发射信号emit g_girl->hungry();
}

在这里插入图片描述

信号槽的拓展

  • 一个信号可以连接多个槽函数, 发送一个信号有多个处理动作
    需要写多个connect()连接
    槽函数的执行顺序是随机的, 和connect函数的调用顺序没有关系
  • 信号的接收者可以是一个对象, 也可以是多个对象
    一个槽函数可以连接多个信号, 多个不同的信号, 处理动作是相同的
    需要写多个connect()连接
  • 信号可以连接信号
connect(const QObject *sender, &QObject::signal, const QObject *receiver, &QObject::siganl-new);
  • 信号槽可以断开信号 --> 很少使用
disconnect(const QObject *sender, &QObject::signal, const QObject *receiver, &QObject::method);

信号连接信号案例

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
//  ui->closeBtn;//>>>>>>>>>>>>>>>>>>通过ui对象可以操纵所创建的按钮g_girl=new GirlFriend;m_me=new Me;//这个hungry是自定义的不由Qt框架提供connect(g_girl,&GirlFriend::hungry,m_me,&Me::eat);connect(g_girl,&GirlFriend::hungry,this,&MainWindow::eatSlot);//信号连接信号connect(ui->hungry,&QPushButton::clicked,g_girl,&GirlFriend::hungry);//信号连接槽函数//connect(ui->hungry,&QPushButton::clicked,this,&MainWindow::hungrySlot);connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::hungrySlot()
{//发射信号emit g_girl->hungry();
}void MainWindow::eatSlot()
{qDebug()<<"喝尿";
}

在这里插入图片描述

信号槽的两种连接方式

Qt5中的处理方式

第二个和第四个参数是函数地址
在这里插入图片描述

Qt4中的处理方式

信号槽函数通过宏SIGNAL和SLOT转换为字符串类型
在这里插入图片描述

Qt5处理信号槽重载问题

signals:void hungry();void hungry(QString msg);
public slots://槽函数void eat();void eat(QString msg);

解决方案1:使用Qt4的信号与槽的机制(慎用,编译器不会报错如果你写错了)

    //Qt4的信号与槽connect(g_girl,SIGNAL(hungry()),m_me,SLOT(eat()));connect(g_girl,SIGNAL(hungry(QString)),m_me,SLOT(eat(QString)));

解决方案2:使用函数指针进行指定

    void(GirlFriend::*girl1)()=&GirlFriend::hungry;void(GirlFriend::*girl2)(QString)=&GirlFriend::hungry;void(Me::*point)(QString)=&Me::eat;void(Me::*pointt)()=&Me::eat;connect(g_girl,girl1,m_me,pointt);connect(g_girl,girl2,m_me,point);// >>>>> Qt5connect(g_girl,girl2,this,&MainWindow::eatSlot);// >>>>>> 信号是带参的而槽函数是不带参的 >>>> 直接就是执行eatSlot

案例

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);
//  ui->closeBtn;//>>>>>>>>>>>>>>>>>>通过ui对象可以操纵所创建的按钮g_girl=new GirlFriend;m_me=new Me;//这个hungry是自定义的不由Qt框架提供
// >>>>>>>>>>>>>> Qt5处理重载void(GirlFriend::*girl1)()=&GirlFriend::hungry;void(GirlFriend::*girl2)(QString)=&GirlFriend::hungry;void(Me::*point)(QString)=&Me::eat;void(Me::*pointt)()=&Me::eat;connect(g_girl,girl1,m_me,pointt);connect(g_girl,girl2,m_me,point);// >>>>> Qt5connect(g_girl,girl2,this,&MainWindow::eatSlot);
//err//connect(g_girl,&GirlFriend::hungry,m_me,&Me::eat);// >>>>> Qt5//connect(g_girl,&GirlFriend::hungry,this,&MainWindow::eatSlot);//Qt4的信号与槽connect(g_girl,SIGNAL(hungry()),m_me,SLOT(eat()));connect(g_girl,SIGNAL(hungry(QString)),m_me,SLOT(eat(QString)));//信号连接信号//connect(ui->hungry,&QPushButton::clicked,g_girl,&GirlFriend::hungry);//信号连接槽函数connect(ui->hungry,&QPushButton::clicked,this,&MainWindow::hungrySlot);connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::hungrySlot()
{//发射信号g_girl->hungry();g_girl->hungry("粑粑");
}void MainWindow::eatSlot()
{qDebug()<<"喝尿";
}

在这里插入图片描述
在这里插入图片描述

lambda表达式

lambda表达式–>匿名函数

[capture](params) opt -> ret {body;};- capture: 捕获列表- params: 参数列表- opt: 函数选项- ret: 返回值类型- body: 函数体
捕获列表: 捕获一定范围内的变量[] - 不捕捉任何变量[&] - 捕获外部作用域中所有变量, 并作为引用在函数体内使用 (按引用捕获)[=] - 捕获外部作用域中所有变量, 并作为副本在函数体内使用 (按值捕获)拷贝的副本在匿名函数体内部是只读的[=, &foo] - 按值捕获外部作用域中所有变量, 并按照引用捕获外部变量 foo[bar] - 按值捕获 bar 变量, 同时不捕获其他变量[&bar] - 按引用捕获 bar 变量, 同时不捕获其他变量[this] - 捕获当前类中的this指针让lambda表达式拥有和当前类成员函数同样的访问权限如果已经使用了 & 或者 =, 默认添加此选项

简单案例

// 匿名函数的定义, 程序执行这个匿名函数是不会被调用的
[](){qDebug() << "hello, 我是一个lambda表达式...";
};// 匿名函数的定义+调用:
int ret = [](int a) -> int
{return a+1;
}(100);  // 100是传递给匿名函数的参数

Qt中的应用

在这里插入图片描述

补充知识点

#include<iostream>
using namespace std;class a
{
public:void print(){cout << "1" << endl;}
};int main()
{a a;  // 创建对象a.print();// 声明成员函数指针并调用void (a:: * print_ptr)() = &a::print;  // 成员函数指针(a.*print_ptr)();  // 通过指针调用
}

在这里插入图片描述

关于lambda

如果第一个信号函数有参数,且第二个信号是通过 lambda 来处理的,需要在 lambda 中接受并传入这些参数。具体来说,lambda 必须与信号的签名匹配,包括参数的类型和数量。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词