Qt信号与槽连接

xiaoxiao2021-02-28  22

信号与槽连接

qt5格式:

connect(pointer1, pointer2, pointer3, pointer4);

pointer1:指向发送信号的对象的指针

pointer2:发送信号的对象所对应的类的成员函数的指针

pointer3:接收信号的对象的指针

pointer4:接收信号的对象所对应对象的槽函数指针

其中pointer2,和pointer4都是函数指针,必须使用类名::成员函数名,并且pointer2和pointer4函数参数类型一致,pointer4会忽略pointer2传递的多余参数,pointer4可以是普通函数(无需public slots:修饰)。

总结下来就是:

信号:只需声明无需实现,且没有返回值;槽函数:QT5类中任意成员函数,静态函数,全局函数,lambda表达式,槽函数可以有返回值,但只有在作为普通函数调用时才能接受,信号触发调用时无法接受;信号与槽使用函数指针形式传入时格式必须是类名::成员函数名(信号或槽);信号和槽的参数列表顺序必须一致;信号和槽的参数个数可以不一致,但要满足信号的参数个数大于等于槽函数参数个数,槽函数会忽略信号传递的多余参数。

例如:

MainWidget.h文件:

class MainWidget : public QWidget { Q_OBJECT public: explicit MainWidget(QWidget *parent = 0); QPushButton * pushButton; SubWidget * subWidget; signals: public slots: void switchWinSlot(); };

MainWidget.cpp文件:

MainWidget::MainWidget(QWidget *parent) : QWidget(parent), pushButton(new QPushButton(this)) { pushButton->setText(QStringLiteral("切换至子窗口")); subWidget = new SubWidget; connect(pushButton, &QPushButton::clicked, this, &MainWidget::switchWinSlot); connect(subWidget, &SubWidget::switchWin, this, &MainWidget::switchWinSlot); subWidget->setWindowTitle("sub"); this->setWindowTitle("parent"); this->resize(400, 300); subWidget->resize(400, 300); }

void MainWidget::switchWinSlot() { this->setVisible(!this->isVisible()); this->subWidget->setVisible(!subWidget->isVisible()); }

另外

一个信号可以连接多个槽,槽函数的执行顺序是随机的,无法控制多个信号可以连接一个槽一个信号可以连接另一个信号(这两个信号可以是不同对象的信号)这里对第三点举例 信号和槽连接成功后,可以断开连接disconnect

subwidget.h文件:

class SubWidget : public QWidget { Q_OBJECT public: explicit SubWidget(QWidget *parent = 0); QPushButton * pushButton; signals: void switchWin(); public slots: };

subwidget.cpp文件:

SubWidget::SubWidget(QWidget *parent) : QWidget(parent) { pushButton = new QPushButton(this); pushButton->setText(QStringLiteral("切换至父窗口")); connect(pushButton, &QPushButton::clicked, this, &SubWidget::switchWin); }

此例子是子窗口产生clicked信号时会同时产生自定义的switchWin信号,用来实现主窗口与子窗口之间的切换

此外

信号和槽函数可以进行重载,利用Qt5格式连接重载的信号和槽时,应该使用函数指针变量对重载信号或槽进行区分

subwidget.h文件:

class SubWidget : public QWidget { Q_OBJECT public: explicit SubWidget(QWidget *parent = 0); QPushButton * pushButton; signals: void switchWin();     void switchWin(bool); public slots: };

subwidget.cpp文件:

SubWidget::SubWidget(QWidget *parent) : QWidget(parent) { pushButton = new QPushButton(this); pushButton->setText(QStringLiteral("切换至父窗口")); void (SubWidget::* pfun)() = &SubWidget::switchWin; void (SubWidget::* pfun2)(bool) = &SubWidget::switchWin; connect(pushButton, &QPushButton::clicked, this, pfun); connect(pushButton, &QPushButton::clicked, this, pfun2); }

上述函数指针涉及到类成员函数的函数指针,详见:

http://blog.csdn.net/xiaoyink/article/details/79439676

这是我们对SubClass的switchWin进行了重载,所以也要对mainwidget.cpp中connect连接switchWin信号的代码进行修改,这里我们用另一种方法,使用static_cast<>运算符对函数指针进行类型转换来区别switchWin的重载;

mainwidget.cpp修改如下:

#include "mainwidget.h" #include <QPushButton> #include "subwidget.h" MainWidget::MainWidget(QWidget *parent) : QWidget(parent), pushButton(new QPushButton(this)) { pushButton->setText(QStringLiteral("切换至子窗口")); subWidget = new SubWidget; connect(pushButton, &QPushButton::clicked, this, &MainWidget::switchWinSlot); //connect(subWidget, &SubWidget::switchWin, this, &MainWidget::switchWinSlot);//修改之前 connect(subWidget, static_cast<void(SubWidget::*)()>(&SubWidget::switchWin), this, &MainWidget::switchWinSlot); subWidget->setWindowTitle("sub"); this->setWindowTitle("parent"); this->resize(400, 300); subWidget->resize(400, 300); } void MainWidget::switchWinSlot() { subWidget->setVisible(!subWidget->isVisible()); this->setVisible(!this->isVisible()); }

上述涉及到的函数指针和重载函数的结合使用可以参考:

http://blog.csdn.net/xiaoyink/article/details/79441277

也可以利用Qt4中的信号与槽连接机制对重载进行区分,但不推荐使用,因为qt4使用宏定义会将函数名转化成字符串,所以并不会提供编译的错误检查,并且,SLOT()宏要求所有的槽函数必须使用xxx(public) slots:关键字进行修饰,qt4格式如下:

    connect(sender, SIGNAL(signal), receiver, SLOT(slot));

最后

connect函数还可以使用lambda表达式,在pro文件中加入CONFIG+=c++11,上述connect语句可以换成

connect(pushButton, &QPushButton::clicked, [=](){ emit switchWin(); });

或者

connect(pushButton, &QPushButton::clicked, [this](){ emit this->switchWin(); });

关于lambda表达式的用法详见:

http://blog.csdn.net/xiaoyink/article/details/79351350

补充

connect()函数可以自己设置第5个参数:

QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

最后一个参数取值及其含义如下:

Qt::AutoConnection (默认)Qt::DirectConnectionQt::QueuedConnectionQt::BlockingQueuedConnection

Qt::UniqueConnection

Qt::AutoConnection:如果信号发送者和接受者在同一个线程,则选用Qt::DirectConnection,如果不在同一个线程,则使用Qt::QueuedConnection做参数;

Qt::DirectConnection:信号发送后,槽函数立即执行,且会将槽函数拉倒信号发送者所在线程执行,所以,发送者和接收者不在同一个线程时,使用此参数要考虑好后果,除非槽函数应该是可重入的,一般禁用这种情况;

Qt::QueuedConnection:信号发送后立即返回,不等槽函数执行完毕,槽函数在接收者所在线程执行,按照接收者线程的正常事件循环队列执行;(The slot is invoked when control returns to the event loop of the receiver's thread.)

Qt::BlockingQueuedConnection:类似Qt::QueuedConnection,只是信号发送后,发送者所在线程阻塞,等待槽函数返回,当发送者和接受者在同一个线程时,应该禁用这种方式,因为他会导致线程死锁,另外如果接收信号的对象所在线程没有事件循环,也会导致发送信号对象所在线程死锁,因为发送的信号无法被事件循环处理,而发送信号的线程却在等待处理结果,所以死锁;

Qt::UniqueConnection:这个标识可以和其他任何标示联合使用(用按位或操作符),它保证一个信号和一个槽之间只能调用一次connect()函数,如果连接已经存在,则调用失败。

转载请注明原文地址: https://www.6miu.com/read-2630199.html

最新回复(0)