Qt 信号槽(笔记)

简介: Qt 信号槽(笔记)

//完整教程地址:https://www.devbean.net/2012/08/qt-study-road-2-catelog/

 

了解信号槽

所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,用自己的一个函数(成为槽(slot))来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。(这里提一句,Qt 的信号槽使用了额外的处理来实现,并不是 GoF 经典的观察者模式的实现方式。)

看一个例子:

先看代码

#include <QApplication>
#include <QPushButton>>
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    QPushButton button("Quit");
    QObject::connect(&button, &QPushButton::clicked, &QApplication::quit);
    button.show();
    return app.exec();
}

代码和上一篇的HelloWorld类型,只不过把文本框换成了按钮(button)

但是有一行是特别的

QObject::connect(&button, &QPushButton::clicked, &QApplication::quit);

connect的常用形式是:

connect(sender,   signal,

           receiver, slot);

四个参数分别是发出信号的对象, 信号, 接收者, 接受者在接到信号后做出的反应(即调用的函数)。

即sender 发生信号 signal后, 就调用receiver的slot函数。

QObject::connect有5种重载

QMetaObject::Connection connect(const QObject *, const char *,
                                const QObject *, const char *,
                                Qt::ConnectionType);
 
QMetaObject::Connection connect(const QObject *, const QMetaMethod &,
                                const QObject *, const QMetaMethod &,
                                Qt::ConnectionType);
//将this指针作为receiver,隐式传入
QMetaObject::Connection connect(const QObject *, const char *,
                                const char *,
                                Qt::ConnectionType) const;
 
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
                                const QObject *, PointerToMemberFunction,
                                Qt::ConnectionType)
 
QMetaObject::Connection connect(const QObject *, PointerToMemberFunction,
                                Functor);

对应位置的参数分别和基本形式对应

从中可以看出

connect()函数的sender和reveicer都是QObject指针,

signal和slot一致,可以是char*,QMethod, PointerToMemberFunction

第5个比较特别 最后一个参数是Functor。 这个类型可以接受 static 函数、全局函数以及 Lambda 表达式。


信号槽要求信号和槽的参数类型一致。允许槽函数的参数可以比信号的少(这样槽会忽略信号传来的多余的参数)

自定义信号槽:

 

这个例子定义了一个发送者Newspaper(报纸),一个接收者Reader(读者)

发送者:报纸 有1个信号,

接受者 :读者 有1个成员函数 在connect时用作槽。

 

// newspaper.h
//Newspaper类 继承了QObject,继承了它的信号槽
class Newspaper : public QObject
{
    //QObject类(及其子类)都要在第1行写Q_OBJECT
    Q_OBJECT
public:
    Newspaper(const QString & name) :
        m_name(name)
    {
    }
 
    void send()
    {
        emit newPaper(m_name);    //emit:发出newPaper()信号, 感兴趣的接受者会关注这个信号
    }
//signals:该类的信号
signals:
    //函数名就是信号,返回值是void,参数是让外界知道的数据。不需要在.cpp中实现
    void newPaper(const QString &name);
 
private:
    QString m_name;
};


reader.h

接收者receiver:Reader

/ reader.h
#include <QObject>
#include <QDebug>
//接收信号,继承QObject ,添加Q_OBJECT
class Reader : public QObject
{
    Q_OBJECT
public:
    Reader() {}
//成员函数 作为 槽函数
    void receiveNewspaper(const QString & name)
    {
        qDebug() << "Receives Newspaper: " << name;
    }
};

main.cpp

在主函数先创建1个newspaper(发送者) 和 1个reader(接收者)

使用函数connect()让我们连接发送者和接收者,及发送者的信号,接收者的槽。

当调用newspaper的send时,send执行函数emit newsPaper 即发送信号newsPaper

接收者reader自动接收信号,调用相应的槽

Reader::receiveNewspaper

执行对应的语句

qDebug() << "Receives Newspaper: " << name;

在控制台输出:

Receives Newspaper: "Newspaper A"

#include <QCoreApplication>
 
#include "newspaper.h"
#include "reader.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
//创建 报纸 和 接受者
    Newspaper newspaper("Newspaper A");
    Reader reader;
    //连接
    QObject::connect(&newspaper, &Newspaper::newPaper,
                     &reader,    &Reader::receiveNewspaper);
    //调用send函数,newspaper的send函数就发送 1个信号newPaper,然后连接者newspaper的reader调用槽函数
    newspaper.send();
 
    return app.exec();
}

注:如果运行出现LINK错误,解决办法:确定代码正确后重新qmake(右键项目,选择qmake)

 

总结:

  • 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
  • 使用 signals 标记信号函数,信号是一个函数声明,返回 void,不需要实现函数代码;
  • 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
  • 使用 emit 在恰当的位置发送信号;
  • 使用QObject::connect()函数连接信号和槽。


相关文章
|
2月前
Qt第二课 核心机制信号槽
Qt第二课 核心机制信号槽
24 1
|
2月前
|
存储 API C++
【Qt 信号槽】深入探索 Qt 信号和槽机制中的引用传递“ (“A Deep Dive into Reference Passing in Qt Signal and Slot Mechanism“)
【Qt 信号槽】深入探索 Qt 信号和槽机制中的引用传递“ (“A Deep Dive into Reference Passing in Qt Signal and Slot Mechanism“)
158 0
|
2月前
【qt】核心机制信号槽(下)
【qt】核心机制信号槽(下)
17 1
|
2月前
|
消息中间件 存储 安全
深入理解 Qt 信号槽:高效沟通的桥梁
深入理解 Qt 信号槽:高效沟通的桥梁
232 1
|
17天前
|
编译器
(16):深入 Qt5 信号槽新语法
(16):深入 Qt5 信号槽新语法
|
27天前
|
编译器
【Qt】Qt中的信号槽
【Qt】Qt中的信号槽
|
2月前
|
消息中间件 算法 开发者
【Qt面试题】多线程情况下, Qt中的信号槽分别在什么线程中执行, 如何控制?
【Qt面试题】多线程情况下, Qt中的信号槽分别在什么线程中执行, 如何控制?
63 1
|
2月前
|
安全 编译器 C++
【Qt 面试题】Qt信号槽机制与优势与不足
【Qt 面试题】Qt信号槽机制与优势与不足
59 1
|
2月前
|
开发框架 算法 Linux
【知识点回顾 】Qt信号槽与Linux信号处理 的处理机制 深入探讨
【知识点回顾 】Qt信号槽与Linux信号处理 的处理机制 深入探讨
65 0