zoukankan      html  css  js  c++  java
  • 自定义信号和槽

    使用connect()可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。

    下面我们看看使用 Qt 的信号槽,实现一个报纸和订阅者的例子:

    有一个报纸类Newspaper,有一个订阅者类Subscriber。Subscriber可以订阅Newspaper。这样,当Newspaper有了新的内容的时候,Subscriber可以立即得到通知。

    #include <QObject>
     ////////// newspaper.h //////////
    class Newspaper : public QObject
    {
        Q_OBJECT
    public:
        Newspaper(const QString & name) :
            m_name(name)
        {
        }
    
        void send()
        {
            emit newPaper(m_name);
        }
    signals:
        void newPaper(const QString &name);
    
    private:
        QString m_name;
    };
    #include <QObject>
    #include <QDebug>
    ////////// reader.h //////////
    class Reader : public QObject
    {
        Q_OBJECT
    public:
        Reader() {}
    
        void receiveNewspaper(const QString & name)
        {
            qDebug() << "Receives Newspaper: " << name;
        }
    };
    #include "mainwindow.h"
    #include <QApplication>
    
    #include <QCoreApplication>
    
    #include "newspaper.h"
    #include "reader.h"
    ////////// main.cpp //////////
    int main(int argc, char *argv[])
    {
        QCoreApplication app(argc, argv);
    
        Newspaper newspaper("Newspaper A");
        Reader reader;
        QObject::connect(&newspaper, &Newspaper::newPaper,
                         &reader,    &Reader::receiveNewspaper);
        newspaper.send();
    
    
        return app.exec();
    }

    Newspaper类解读

    首先看Newspaper这个类。这个类继承了QObject类。只有继承了QObject类的类,才具有信号槽的能力。所以,为了使用信号槽,必须继承QObject。凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于 C++ RTTI 的反射能力。

    Newspaper类的 public 和 private 代码块都比较简单,只不过它新加了一个 signals。signals 块所列出的,就是该类的信号。信号就是一个个的函数名,返回值是 void(因为无法获得信号的返回值,所以也就无需返回任何值),参数是该类需要让外界知道的数据。信号作为函数名,不需要在 cpp 函数中添加任何实现。

    Newspaper类的send()函数比较简单,只有一个语句emit newPaper(m_name);。emit 是 Qt 对 C++ 的扩展,是一个关键字(其实也是一个宏)。emit 的含义是发出,也就是发出newPaper()信号。感兴趣的接收者会关注这个信号,可能还需要知道是哪份报纸发出的信号?所以,我们将实际的报纸名字m_name当做参数传给这个信号。当接收者连接这个信号时,就可以通过槽函数获得实际值。这样就完成了数据从发出者到接收者的一个转移。

    Reader类解读

    Reader类更简单。因为这个类需要接受信号,所以我们将其继承了QObject,并且添加了Q_OBJECT宏。后面则是默认构造函数和一个普通的成员函数。Qt 5 中,任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数。与信号函数不同,槽函数必须自己完成实现代码。槽函数就是普通的成员函数,因此作为成员函数,也会受到 public、private 等访问控制符的影响。

    自定义信号槽需要注意的事项

    发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);

    使用 signals 标记信号函数,信号是一个函数声明,返回 void,不需要实现函数代码;

    槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;

    使用 emit 在恰当的位置发送信号;

    使用QObject::connect()函数连接信号和槽。

    任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数

    信号槽的更多用法

    (1)一个信号可以和多个槽相连 

      如果是这种情况,这些槽会一个接一个的被调用,但是它们的调用顺序是不确定的。 

    (2) 多个信号可以连接到一个槽 

      只要任意一个信号发出,这个槽就会被调用

    (3)一个信号可以连接到另外的一个信号 

      当第一个信号发出时,第二个信号被发出。除此之外,这种信号-信号的形式和信号-槽的形式没有什么区别。

    (4)槽可以被取消链接 

      这种情况并不经常出现,因为当一个对象delete之后,Qt自动取消所有连接到这个对象上面的槽

    (5)使用Lambda 表达式 

      在使用 Qt 5 的时候,能够支持 Qt 5 的编译器都是支持 Lambda 表达式的。

  • 相关阅读:
    【转】Android Lint分类及常见错误
    备忘
    【转】QRCode二维码生成方案及其在带LOGO型二维码中的应用
    如何控制横向和纵向滚动条的显隐?
    网页屏保
    过度方式
    让背景图不滚动
    自定义指定区域的文字大小
    定义本网页关键字
    通过层来实现渐淡淡出
  • 原文地址:https://www.cnblogs.com/xumaomao/p/12584807.html
Copyright © 2011-2022 走看看