一次吃透Qt中信号与槽(包含信号与槽的使用,自定义以及重构示例,建议收藏)

本文详细介绍了Qt中的信号与槽机制,它是Qt编程的核心特性,简化了对象间的交互。通过示例展示了如何使用QObject::connect函数建立信号和槽的关联,以及如何自定义信号和槽,包括带参数的重载。文章还强调了信号和槽的参数匹配规则,并提供了实际操作案例。
摘要由CSDN通过智能技术生成

1、Qt中信号和槽

信号与槽

信号与槽(Signal & Slot)是 Qt 编程的基础,也是 Qt 的一大创新。因为有了信号与槽的编程机制,在 Qt 中处理界面各个组件的交互操作时变得更加直观和简单。它可以让应用程序编程人员把这些互不了解的对象绑定在一起。

信号(Signal)

信号(Signal)就是在特定情况下被发射的事件,例如PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号,一个 ComboBox 最常见的信号是选择的列表项变化时发射的 CurrentIndexChanged() 信号。

GUI 程序设计的主要内容就是对界面上各组件的信号的响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。

槽(Slot)

就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

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

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

参数1、信号的发送者

参数2、发送的信号

参数3、信号的接收者

参数4、处理函数(槽函数)

案例实操:

现在我们点击关闭窗口整个按钮,我们是,没有任何反应的,我现在在要想点击该按钮实现关闭窗口的功能。那么就得给他们之间建立信号与槽的联系

理解:按钮接收一个鼠标单击的信号,马上,窗口就执行关闭函数。

  1. 首先我们查看按钮QPushButton可以接收哪些信号?在帮助文档索引中搜索QPushButton

 

在QPushButton类中是找不到Signals的,要在他的父类QAbstractButton中查看。

  1. 可以看到他可以接收这4种信号。

我们现在就先尝试使用第一个,单击信号。实现单击按钮关闭窗口

  1. 关闭谁呢,关闭窗口,哪个窗口呢?我们自己新建的Widget窗口,那么我们有实现它的关闭吗?并没有,那么我们需要自己先实现一个吗?不需要,我们可以看

Widget类,其实是QDialog的子类,而QDialog又是QWidget的子类,所以我们去帮助文档看看QWidget,直接在Public Slots种找,

第一个就是close()函数,应该就是关闭窗体的实现,也可以点进去看看。

  1. 现在我们实现信号槽的4个要素,就已经凑齐了,信号发送者是按钮我们new的是btn,发送的信号是clicked单击信号,信号接收者是this,就是本窗口嘛,槽函数是close,现在就好说了,可以让他们建立联系。
  2. 实现信号和槽的机制.
    a.首先我们在窗口中添加按钮
    //窗口头文件中田间
    #include "qpushbutton.h"
    
    //窗口头文件中添加按钮
    private:
        Ui::Widget *ui;
         QPushButton* btn;
    
    //窗口.cpp中添加
     btn=new QPushButton;
         btn->setText("关闭窗口");
         btn->setParent(this);//选择父对象
         btn->resize(120,70);//
         btn->move(100,180);
         connect(btn,&QPushButton::clicked,this,&QWidget::close);//clicked是信号,click是槽,注意区分
     //注意,在信号函数,和槽函数前需要加&号。

  3. 编译,执行,点击“关闭窗口”按钮便可以关闭窗口。
  4. 总结:将本来没有连接的两个对象,连接在一起。本来点击按钮,跟关闭窗口没有联系,我们可以同connect让他们建立起联系。          

2、Qt中自定义信号和槽函数

那么我们是否可以自定以信号和槽函数呢?答案是:按当当然是可以的。

在这个的基础上,我们先设定一个需求:

土豆发向苹果,发送信号,苹果接收信号,并回应:土豆收到。

这里面有两个对象,一个土豆,一个番茄,我们将使用自定义的信号和槽将他们联系起来。

  1. 首先新建两个类,一个,一个Vegetables,一个Fruits。

以Vegetables为例 右击项目>add new

选择C++Class,选择。

类名自定义Vegetables,选择QObject为基类是为了将此类加入qt children中,而QObject是最基本的基类。以同样的方式创建Fruits类。

  1. 在Vegetables类的头文件中加入自定义信号
#ifndef FRUITS_H
#define FRUITS_H

#include <QObject>

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

signals:
    添加代码
    void send();//信号函数返回值为void ,且不需要定义
};

#endif // FRUITS_H
  1. 在Fruits类的头文件和源文件中添加自定义槽函数的定义和实现
#ifndef VEGETABLES_H
#define VEGETABLES_H

#include <QObject>

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

signals:
    
public slots:
    //添加槽函数
    void ask();
};

#endif // VEGETABLES_H

 快捷添加定义,高亮后按住Alt+Enterf

#include "vegetables.h"
#include<QtDebug>//添加头文件
Vegetables::Vegetables(QObject *parent) : QObject(parent)
{
    
}

void Vegetables::ask()
{
        qDebug()<<"我是土豆,收到收到\n";//收到single 后输出到输出栏
}
  1. 在widget.h中的widget类中添加两个成员,Fruits对象pg(苹果),Vegetables对象td(小姐姐)两个指针。
两个头文件
#include "fruits.h"
#include "vegetables.h"

私有类中
private:
    Ui::Widget *ui;
    QPushButton* btn;
    Fruits *pg;
    Vegetables *td;
  1. 在widget.cpp中new出对象并添加连接。
   pg=new Fruits(this);
     td=new Vegetables(this);
     //connect 联立
     connect(pg,&Fruits::send,td,&Vegetables::ask);//注意此处传入的是函数指针,所以不需要打括号
     pg->send();
  1. 运行程序,程序在表白函数中发送single,接收者收到信息并执行相应的槽函数。

运行结果:打印出了槽函数中的信息。实现了自定义的信号和槽函数

 如果显示含有换行符,这是由于QT编码问题,把槽函数的输出文字中的中文符号换成英文符号就好。

  1. 总结:自定义信号和槽的区别,信号和槽都为void类型,信号只需要定义,不需要实现,而槽函数既需要定义,也需要实现信号和槽都可以有参数也都可以重载。emit是出发信号的标志,可要可不要。

                                                                                                                                                                                                                           

3、自定义信号带参数重载问题

自定义信号带参数重载问题

上节课我们讲到,信号和槽都是可以带参数重载的,选择的我们就来学习带参数重载后的问题,及解决的办法。

首先看需求,苹果发送信号成功后,苹果说“开始执行任务”,土豆收到信号后就回复“土豆收到”,这之间的话,就通过信号的参数来传递。

好,还是来到我们上节课的项目。

  1. 在fruits.h的signals下重载send函数,带一个QString参数,就是这个传过去一句话,女孩也说这句话。
    signals:
        //添加代码
        void send();//信号函数返回值为void ,且不需要定义
        void send(QString);//重载一个含有QString的参数

记住,这个信号只需要定义,不需要实现,只要知道定义了这么一个带一个参数的信号就行了。触发这个信号,还需要一个QString的参数。

  1. 在vegetables.cpp也重载一个带参数的回应的槽函数
    public slots:
        //添加槽函数
        void ask();
        void ask(QString);
    void Vegetables::ask(QString)
    {
        qDebug()<<str;
        qDebug()<<"土豆收到,保证完成任务";
    }

    添加连接

         //在weight.cpp中添加
        void(Fruits::*pSent)(QString)=&Fruits::send;
         void(Vegetables::*Ack)(QString)=&Vegetables::ask;
         connect(pg,pSent,td,Ack);
         pg->send("土豆执行任务");

        执行结果:

多个信号可以连接同一个槽函数

这个就不用实例了,我们的按钮和窗口上的xx都可以关闭窗口。

信号和槽的参数必须一一对应。

信号的发送什么,槽就接收什么,类型必须一致。但信号的参数个数可以多余槽的参数的个数,但前面相同数量的参数类型必须一一对应。反之则不可以。

今天的分享就到这里来,希望大家看完之后能够准确的掌握QT信号和槽,第一次写博客,希望大家多多支持,给一个免费的关注和赞,后期我会在CSDN分享QT,MFC,MYSQL,C++重难点和数据库方面的学习经验,希望大家多多支持!!!

  • 9
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值