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
特在此表示十分感谢!