用户登录
用户注册

分享至

还没理解Qt的自定义信号与槽吗?快来看这篇文章

  • 作者: 别点开我头像
  • 来源: 51数据库
  • 2021-07-30

前言

上个学期由于需要做一个期末大作业,于是决定使用Qt写一个学生管理系统,如图。在做这个项目的过程中,对于Qt的信号与槽有了更为深刻的认识(如对本人此项目有想法,可与我联系)。
本文不涉及较深的Qt底层实现,仅谈谈我个人的理解。

文章目录

  • 前言
  • 一、什么是信号与槽
    • 1.打电话
    • 2.将打电话这一系列动作放到Qt程序当中应该是怎样的
      • 普通信号的传递
  • 二、信号、槽
    • 普通的信号与槽
    • 自定义信号与槽
      • 准备工作
      • 头文件成员变量说明
      • 流程
        • 发送自定义信号
        • 接收自定义信号,触发自定义槽函数
  • 自定义信号与槽的关键
  • 结语

提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是信号与槽

1.打电话

我们知道,现实生活中,每个人几乎每时每刻都在接收信息,处理事件。
举个打电话的例子,
当来电话时,“来电话了”就是一个事件,
也就是说,“来电话了”这个事件发生了,
而你听到了“电话铃声”,这个“电话铃声”就相当于一个信号,
于是你“接听”了它,
这就意味着你接收了“电话声”这个信号,处理了它并作出回应,回应的方式就是“接听”。

2.将打电话这一系列动作放到Qt程序当中应该是怎样的

我们再回味回味,将这一系列动作放到Qt程序当中应该是怎样的:Qt的事件监听就相当于人的大脑在接收生活中的信息。
电话响了本身讲就是一个事件,那么我们如何得知事件已经发生呢?当然是通过电话发出的电话铃声了。
而这个电话铃声就是Qt发出的信号,我们就可以通过connect函数亦或是直接使用事件监听器去获取到这个信号(本文仅讨论connect函数的情况),然后通过槽函数,我们就可以处理这些信号,做一些文章。

普通信号的传递

二、信号、槽

普通的信号与槽

QPushButton* btn = new QPushButton("按钮1", this);
connect(btn,&QPushButton::clicked,[](){
	//CODEBLOCKS
});

当然,如果你查阅了Qt助手会发现,QPushButton继承于QAbstractButton类,而QAbstractButton类中有一个clicked信号:void clicked(bool checked = false)会发现它携带了一个参数,那么上面的代码中匿名槽函数怎么没有携带参数呢?难道信号与槽的参数不是一一对应的吗?
当然是一一对应的,只不过由于这个信号携带了默认值,所以这种情况下槽函数可以的参数可以省略。

自定义信号与槽

准备工作

首先我们先定义一个MainWindow窗口(由于我是在Visual Studio2019中编写的代码,所以部分头文件于Qt自身有些不一样,但不影响学习)
请允许我先抛出实现的代码,然后听我娓娓道来。

SignalAndSlot.h

#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_SignalAndSlot.h"
#include <qpushbutton.h>
#include <qtextedit.h>
class SignalAndSlot : public QMainWindow
{
    Q_OBJECT

public:
    SignalAndSlot(QWidget *parent = Q_NULLPTR);
    QPushButton* btn;//举例用的按钮组件
    QTextEdit* editText;//文本编辑框
    void init();//初始化组件函数
    void sendMySignal();//中间人
    void getEditTextContent(QString text);//接收文本消息的槽函数


private:
    Ui::SignalAndSlotClass ui;

signals:
    void mySignal(QString msg);//自定义信号
};

在上述头文件中,btn与editText为我们的示例组件,init函数用于分配组件的内存、简单布局以及信号与槽函数的绑定。

头文件成员变量说明

成员变量用途
pubilcbtn按钮示例组件
pubilceditText文本编辑框示例组件
pubilcvoid init()分配组件的内存、简单布局以及信号与槽函数的绑定。
pubilcvoid sendMySignal()将绑定于按钮的clicked信号的槽函数,当触发clicked信号时,发送mySignal信号
pubilcvoid getEditTextContent(QString text)将绑定于mySigal信号的槽函数,当触发mySignal信号时,获取到文本键框的文本消息
privateuiQt的ui类,用于绘制界面,本文不涉及
signalsvoid mySignal(QString msg)自定义信号

SignalAndSlot.cpp

#include "SignalAndSlot.h"
#include <qmessagebox.h>
#pragma execution_character_set("utf-8")
SignalAndSlot::SignalAndSlot(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    init();
}

/*初始化界面及事件绑定*/
void SignalAndSlot::init()
{
    btn = new QPushButton("按钮1", this);//一个按钮
    btn->move(200, 0);
    editText = new QTextEdit(this);//一个文本编辑框
    editText->resize(200, editText->size().height());

	
    connect(btn, &QPushButton::clicked, this, &SignalAndSlot::sendMySignal);//将按钮clicked信号与sendMySignal函数绑定
    connect(this, &SignalAndSlot::mySignal, this, &SignalAndSlot::getEditTextContent);//将mySignal这个自定义信号与getEditTextContent函数绑定
}

/*发送自定义信号-中间人*/
void SignalAndSlot::sendMySignal()
{
    QString text = this->editText->toPlainText();
    if (text.isEmpty() == false) {
        emit mySignal(text);//如果文本不为空,则将自定义信号发送出去,否则无事发生
    }
}

/*获取文本编辑框消息-自定义槽函数*/
void SignalAndSlot::getEditTextContent(QString text)
{
    if (text.isEmpty() == false) {//如果消息传递过来的值不为空,则提示消息内容
        QMessageBox::information(this, "内容:", text);
    }
    else {
        QMessageBox::warning(this, "Error:", "您还没输入内容呢!!!");
    }
}

流程

发送自定义信号

connect(btn, &QPushButton::clicked, this, &SignalAndSlot::sendMySignal);//将按钮clicked信号与sendMySignal函数绑定

当我们单击按钮,由于使用了connect函数,将clicked信号与sendMySignal()函数进行了绑定。
于是单击按钮时,由于按钮被单击后会触发clicked信号,通过connect后,sendMySignal()函数将会被执行,
而从上述代码中可以看到,sendMySignal()函数会获取文本编辑框的内容,然后判断文本是否为空,若不为空,则emit mySignal(text);在信号中附加编辑框内容的文本数据,将信号发送出去。

接收自定义信号,触发自定义槽函数

connect(this, &SignalAndSlot::mySignal, this, &SignalAndSlot::getEditTextContent);//将mySignal这个自定义信号与getEditTextContent函数绑定

通过上述代码,将mySignal与getEditTextContent函数进行了绑定。那么一切就可以顺其自然的发生了。


由于clicked信号与sendMySignal函数绑定,mySignal信号与getEditTextContent函数绑定。
当clicked信号触发后,sendMySignal槽函数将会获取到文本内容,然后附加到mySignal信号中并发送。而mySignal信号又与getEditTextContent槽函数绑定,所以当mySignal信号触发时,getEditTextContent就会取出信号的文本数据,并用信息框进行展示。
于是当按钮按下后,信息框就会弹出文本编辑框的文本数据。
这就类似于A->B; B->C; 于是可以推出A->C
于是乎,自定义信号与槽的功能就实现了。

自定义信号与槽的关键

其实,如果你足够细心,你应该能够注意到,无论是现实中的接电话案例还是获取获取编辑框的信息,他们都有一个中间人的角色,而这个中间人就是槽函数sendMySignal
在接电话案例当中,你的大脑就充当了一个中间人的角色,电话铃响,意味着事件发生并且你的大脑监听到了。你选择了接听它说明你的大脑通过电话铃声做出了响应。作出响应的这个过程就对应着自定义槽的函数的实现。
那么怎么判断哪个槽函数是中间人呢?

谁转发的信号,谁就是中间人。

结语

2020 - 996 = 1024
告别996,从1024开始!

软件
前端设计
程序设计
Java相关