zoukankan      html  css  js  c++  java
  • Qt 信号与槽

    使用connect()可以让我们连接系统提供的信号和槽。

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

    这也是 Qt 框架的设计思路之一,用于我们设计解耦的程序。

    // !!! Qt 5
    #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();
    }

     信号槽不是 GUI 模块提供的,而是 Qt 核心特性之一。因此,我们可以在普通的控制台程序使用信号槽。

    只有继承了QObject类的类,才具有信号槽的能力。所以,为了使用信号槽,必须继承QObject

    凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。

    这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于 C++ RTTI 的反射能力。

    因此,如果你觉得你的类不需要使用信号槽,就不添加这个宏,就是错误的。其它很多操作都会依赖于这个宏。

    注意,这个宏将由 moc(我们会在后面章节中介绍 moc。这里你可以将其理解为一种预处理器,是比 C++ 预处理器更早执行的预处理器。) 做特殊处理,不仅仅是宏展开这么简单。

    moc 会读取标记了 Q_OBJECT 的头文件,生成以 moc_ 为前缀的文件。

    signals 块所列出的,就是该类的信号。信号就是一个个的函数名,返回值是 void(因为无法获得信号的返回值,所以也就无需返回任何值),参数是该类需要让外界知道的数据。

    信号作为函数名,不需要在 cpp 函数中添加任何实现(我们曾经说过,Qt 程序能够使用普通的 make 进行编译。没有实现的函数名怎么会通过编译?原因还是在 moc,moc 会帮我们实现信号函数所需要的函数体,所以说,moc 并不是单纯的将 Q_OBJECT 展开,而是做了很多额外的操作)

    emit newPaper(m_name);  

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

    Qt 5 中,任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数。与信号函数不同,槽函数必须自己完成实现代码。

    槽函数就是普通的成员函数,因此作为成员函数,也会受到 public、private 等访问控制符的影响。(我们没有说信号也会受此影响,事实上,如果信号是 private 的,这个信号就不能在类的外面连接,也就没有任何意义。)

    总结一下自定义信号槽需要注意的事项:

    • 发送者和接收者都需要是QObject的子类(当然,槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
    • 使用 signals 标记信号函数,信号是一个函数声明,返回 void,不需要实现函数代码;
    • 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
    • 使用 emit 在恰当的位置发送信号;
    • 使用QObject::connect()函数连接信号和槽。
    //!!! Qt5
    #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;
    };
    
    ////////// reader.h
    #include <QObject>
    #include <QDebug>
    
    class Reader : public QObject
    {
        Q_OBJECT
    public:
        Reader() {}
    
        void receiveNewspaper(const QString & name)
        {
            qDebug() << "Receives Newspaper: " << name;
        }
    };
    
    ////////// main.cpp
    #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);
        newspaper.send();
    
        return app.exec();
    }

    原文: https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot/

  • 相关阅读:
    Spring MVC 支持 RESTful 风格编程
    SpringMVC 目标方法返回 json 格式数据
    SpringMVC 文件上传
    使用Eclipse 创建 Maven 项目
    SpringMVC 环境搭建
    SpringMVC运行原理
    Linux(centos)下SVN服务器的搭建及简单配置和使用
    Linux 后台执行脚本命令
    C++入门教程,C++基础教程 更新中...
    Mac开发之HID通讯开发
  • 原文地址:https://www.cnblogs.com/nanqiang/p/9999347.html
Copyright © 2011-2022 走看看