信号槽

1.信号槽的实现:顾名思义,信号槽机制包含了信号,槽,其实还包含了联系两者的“红娘”。

当某一事件发生后,我们默认它会产生一个独一无二信号,这种信号会传播到他能传播到的每一处。

一旦某一个函数所关注的信号被其接受了,那么他就会执行自己的工作。我们将这个函数就定义为槽。

QObject类中有一个含数:connect,我们可以利用它来进行“牵线功能”,将信号与槽一一对应的连接起来。

下面上一份代码来具体分析语法:

#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

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

    button.show();

    return a.exec();
}

 QPushButton类和Qlabel的功能类,只不过是产生的不是标签而是一个按钮。我们可以在其后紧跟一对括号,并在括号内填入字符串用以为其命名。

由于是个插件,所以需要使用button.show();来对他进行显示。

先面对connect函数进行一个详细的学习:

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);
 
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的重载函数进行分析:

connet的参数包含了5个部分:发送对象sender,发送信号signal,接收对象receiver,接受后反应slot,联系方式。常用的参数有前四个,第五个参数我们常使用其缺省模式下的默认值。

第一个,sender 类型是 const QObject *,signal 的类型是 const char *,receiver 类型是 const QObject *,slot 类型是 const char *。这个函数将 signal 和 slot 作为字符串处理。

第二个,sender 和 receiver 同样是 const QObject *,但是 signal 和 slot 都是 const QMetaMethod &(使用使用函数的地址(指针)替换)。

第三个,sender 同样是 const QObject *,signal 和 slot 同样是 const char *,但是却缺少了 receiver。这个函数其实是将 this 指针作为 receiver。

第四个,sender 和 receiver 也都存在,都是 const QObject *,但是 signal 和 slot 类型则是 PointerToMemberFunction(指向成员函数的指针)。

第五个,前面两个参数没有什么不同,最后一个参数是 Functor 类型。这个类型可以接受 static 函数、全局函数以及 Lambda 表达式。

 

此时再回头分析我们的代码得到:我们使用的是第五个函数的表示方法。其中sender是QPushButton类的对象。signal是一个该类的成员函数指针。

               我们没有设置接受者,表明只要产生这个信号就会在任一情况下进行QApplication的一个static函数qiut的功能。

 2.自定义信号槽:

 只前介绍的都是系统自带的信号槽,信号槽功能强大就在于我们可以自己去定义我们所需要的信号槽。

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

注:只有继承了 QObject 类的类,才具有信号槽的能力。凡是 QObject 类(不管是直接子类还是间接子类),都应该在第一行代码写上 Q_OBJECT。

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

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

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

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

#ifndef E_MAIL_H
#define E_MAIL_H

//“e_mail.h”
#include <QObject>

class E_mail : public QObject
{
    Q_OBJECT
private:
    QString name;
    QString txt;
    QString author;
    mutable E_mail* receivedemail;
public:
    E_mail();
    E_mail(QString name, QString author, QString txt);
    void send();
    void receive(E_mail* receivedemail);
    void look_the_receivedemail();

signals:
    void send_a_email(E_mail* email);
};

#endif // E_MAIL_H

 

//e_mail.cpp
#include "e_mail.h"
#include <QObject>
#include <QDebug>

E_mail::E_mail(){
    this -> name = "NULL";
    this -> author = "NULL";
    this -> txt = "NULL";
}
E_mail::E_mail(QString name, QString author, QString txt){
    this -> name = name;
    this -> author = author;
    this -> txt = txt;
    this -> receivedemail = NULL;
}
void E_mail::send(){
    emit send_a_email(this);
}
void E_mail::receive(E_mail* receivedemail){
    this -> receivedemail = receivedemail;
}
void E_mail::look_the_receivedemail() {
    qDebug() << "received from: " << receivedemail -> author;
    qDebug() << "email title is: " << receivedemail -> name;
    qDebug() << "email content is: " << receivedemail -> txt;
}
#include <QApplication>
#include "e_mail.h"
#include <QPushButton>
#include <QObject>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    E_mail newemail((QString)"Final Text Grade",(QString)"Teacher Wang", (QString)"Chinese: 90, English: 85, Math: 95");
    E_mail receiver;
    QPushButton button_print("Print");
    QObject::connect(&newemail, &E_mail::send_a_email, &receiver, &E_mail::receive);
    QObject::connect(&button_print, &QPushButton::clicked, &receiver, &E_mail::look_the_receivedemail);
    newemail.send();
    button_print.show();
    return a.exec();
}

正如代码中所示,我们的定义了一个类,叫做:e_mail, 对于其私有变量和一部分函数我就不再过多叙述,无论是实现还是原理都十分易懂。

有两处雪要注意:

1. 信号的声明格式是:

signals:
    void function_name(type of the param sending to slot);

2.信号的发送:emit是c++的一个关键字,此处用于发送一个信号。

emit signals’ function name (the param to slot);//参数类型需要和信号内声明的函数里声明的参数类型一致。

 

参考网站:

豆子老师的博客:http://www.qter.org/forum.php?mod=viewthread&tid=622

特在此表示十分感谢!

 

posted @ 2019-03-08 16:44  水尺  阅读(575)  评论(0编辑  收藏  举报