信号槽机制是Qt的非常重要的机制,本文不剖析信号槽机制的原理,只讲信号的主要使用方法。
信号:当某个事件发生后,比如按钮检测到自己被点击了一下,按钮会发出一个信号,这种发出是没有目的的,类似广播。
1. 信号连接槽 connect函数
connect函数最常用的一般形式:
connect(sender, signal, receiver, slot);
2. 解除信号和连接到信号的槽的连接 disconnect函数
disconect函数的原型如下:
bool QObject::disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
一般有四种用法:
2.1 解除myObject对象的所有信号连接,调用后myObject对象发出的所有信号都得不到响应。
disconnect(myObject, 0, 0, 0);
//等同于
myObject->disconnect();
2.2 解除myObject对象的mySignal信号的所有连接,调用后myObject对象发出的mySignal信号得不到响应。
disconnect(myObject, SIGNAL(mySignal()), 0, 0);
//等同于
myObject->disconnect(SIGNAL(mySignal()));
2.3 解除myObject对象与myReceiver对象的信号连接,调用后myObject对象发出的所有信号得不到myReceiver对象的响应。
disconnect(myObject, 0, myReceiver, 0);
//等同于
myObject->disconnect(myReceiver);
2.4 解除myObject对象的mySignal信号与myReceiver对象的mySlot槽的连接,调用后myObject对象发出的mySignal信号得不到myReceiver对象的mySlot槽的响应。
disconnect(myObject, SIGNAL(mySignal()), myReceiver, SLOT(mySlot()));
//等同于
myObject->disconnect(SIGNAL(mySignal(), myReceiver, SLOT(mySlot())));
ps:上述4种用法中,0是通配符,它表示任一信号、任一接收对象、任一槽。
3. 阻塞信号 blockSignals函数
blockSignals的函数原型如下:
bool QObject::blockSignals(bool block)
用法:
//object发出的信号被阻塞,系统不会调用任何连接到object的处理。
object->blockSignals(true);
//解除信号阻塞
object->blockSignals(false);
4.案例
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget(){}
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include <QPushButton>
#include <QGridLayout>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
/* 创建控件 */
QPushButton *btnClick = new QPushButton("click me", this);
QPushButton *btnBlock = new QPushButton("block", this);
QPushButton *btnUnblock = new QPushButton("unblock", this);
QPushButton *btnDisconnect = new QPushButton("disconnect", this);
QGridLayout *pLayout = new QGridLayout();
pLayout->addWidget(btnClick, 0, 0);
pLayout->addWidget(btnBlock, 0, 1);
pLayout->addWidget(btnUnblock, 0, 2);
pLayout->addWidget(btnDisconnect, 0, 3);
this->setLayout(pLayout);
/* 信号槽 */
connect(btnClick, &QPushButton::clicked, this, [=]()
{
qDebug() << "点击按钮";
});
connect(btnBlock, &QPushButton::clicked, this, [=]()
{
btnClick->blockSignals(true);
btnBlock->setEnabled(false);
btnUnblock->setEnabled(true);
});
connect(btnUnblock, &QPushButton::clicked, this, [=]()
{
btnClick->blockSignals(false);
btnBlock->setEnabled(true);
btnUnblock->setEnabled(false);
});
connect(btnDisconnect, &QPushButton::clicked, this, [=]()
{
disconnect(btnClick, &QPushButton::clicked, this, 0);
});
}
//main.c
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
结果:
1.按下"click me"按钮,窗口接收到"click me"按钮发出的clicked信号,打印"点击按钮"。
2.然后再按下"block",再次按下"click me"按钮,没有打印"点击按钮"。这是因为 "click me"按钮发出的信号被阻塞了,没有得到响应。
3.然后再按下"unblock"按钮,再次按下"click me"按钮,打印"点击按钮"。这是因为解除了"click me"按钮的信号阻塞。
4.最后按下"disconnect"按钮,此时按下"click me"按钮没有反应。这是因为解除了本窗口与"click me"按钮的clicked信号的连接。
//----------------------分割线-------------------------
更新:
信号还可以连接信号,举例如下,当ui->mdiArea的信号发出时,proWid的信号被发出。
connect(ui->mdiArea, &QMdiArea::subWindowActivated,
proWid, &ProjectWidget::subWindowActivated);