connect研究

来源:互联网 发布:旅游沙盘教学软件 编辑:程序博客网 时间:2024/06/03 20:44

问题的提出

对于一个图形界面来说,图形界面变成那个不仅需要运行时的高效性,还需要在C++对象模型的基础上添加了一些特性,形成了自己的对象模型,比如信号和槽,就是一个强大的无缝对象通信机制——信号和槽。
而connect函数就是连接信号和槽的最为关键的一点,下面将通过一个具体的工程来实现,举例如下:

Connect工程效果
整体效果

这里写图片描述

点击PushButton后的效果

这里写图片描述

点击Child Dialog后的效果

这里写图片描述

Connect工程的头文件
#ifndef FATHERDIALOG_H#define FATHERDIALOG_H#include <QDialog>namespace Ui {class FatherDialog;}class FatherDialog : public QDialog{    Q_OBJECTpublic:    explicit FatherDialog(QWidget *parent = 0);    ~FatherDialog();private slots:    void on_pushButton_clicked();    void showChildDialog();    void on_childB_clicked();    void on_childB_clicked(bool checked);private:    Ui::FatherDialog *ui;};#endif // FATHERDIALOG_H
Connect工程头文件的具体实现方法
#include "fatherdialog.h"#include "ui_fatherdialog.h"#include <QMessageBox>FatherDialog::FatherDialog(QWidget *parent) :    QDialog(parent),    ui(new Ui::FatherDialog){    ui->setupUi(this);    QObject::connect(ui->childB,                     &QPushButton::clicked,                     this,                     &FatherDialog::showChildDialog);}FatherDialog::~FatherDialog(){    delete ui;}void FatherDialog::on_pushButton_clicked(){    QMessageBox::information(this,"提示","<font size='26'>请告诉我为什么</font>",QMessageBox::Ok);}void FatherDialog::showChildDialog(){    QDialog * d= new QDialog(this);    d->show();}
Connect工程的主函数
#include "fatherdialog.h"#include <QApplication>int main(int argc, char *argv[]){    QApplication a(argc, argv);    FatherDialog w;    w.show();    return a.exec();}
重要部分是信号和槽关联的部分,下面进行分析

槽和信号的关联使用的是QObject类的connect()函数,该函数的原型如下:

bool QObject::connect (const QObject * sender, const char * signal, const QObject * receiver, const char * slot) [static]
信号

当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。

信号只需要在头文件中进行声明,不需要在cpp中实现。放在Qt自定义关键字signals下,在此之前一定要加上Q_OBJECT宏。当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号。这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用。在编程中,一般使用的是控件内部定义好的信号。如:QTreeWidget类下的 Signals,也可以自定义信号,并通过emit在代码中发射信号。

关联信号和槽(connect)

之前connect()函数的调用方式为

    QObject::connect(ui->childB,                     &QPushButton::clicked,                     this,                     &FatherDialog::showChildDialog);

注意
在connect函数中信号函数和槽函数若有参数,只能写出参数类型,而不能也将变量名写出;否则,连接会失败!

一个信号可以连接多个槽当信号发射时,会以不确定的顺序一个接一个的调用各个槽。

多个信号可以连接同一个槽即无论是哪一个信号被发射,都会调用这个槽。

信号直接可以相互连接发射第一个信号时,也会发射第二个信号。

断开信号和槽(disconnect)
当信号和槽没有必要继续保持连接时,可以通过调用disconnect来断开它们。
bool QObject::disconnect (const QObject * sender, const char * signal,  const Object * receiver, const char * slot) [static]

(1)断开与某个对象相关联的任何对象。

disconnect(sender, 0, 0, 0) ;//或者sender->disconnect();

(2)断开与某个特定信号的任何关联。

disconnect(sender, SIGNAL(signal()), 0, 0);//或者sender->disconnect(SIGNAL(signal()));

(3)断开两个对象之间的关联。

disconnect(sender, 0, receiver, 0);//或者sender->disconnect(receiver);
应该注意的问题

信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。例如 , 在前面给出的例子中如果在 mySlot() 槽函数中加上语句 emit mySignal() 即可形成死循环。
如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。
宏定义不能用在 signal 和 slot 的参数中。
信号和槽的参数个数与类型必须一致。

原创粉丝点击