信号槽是Qt框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的。类似广播。如果有对象对这个信号感兴趣。它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
connect(sender,signal,receiver,slot);
参数解释:
sender:发出信号的对象;
signal:发送对象发出的信号
receiver:接收信号的对象
slot:接收对象在接收到信号之后所需要调用的函数(槽函数)
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
QPushButton *p;
~Widget();
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
p = new QPushButton("关闭",this);
//设置连接,点击按钮产生信号,会调用窗口的close函数
connect(p,&QPushButton::clicked,this,&QWidget::close);
}
Widget::~Widget()
{
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
QPushButton *p;
~Widget();
//声明槽函数
public slots:
void print();
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
p = new QPushButton("按下",this);
//设置连接,点击按钮产生信号,会调用窗口的自定义的函数
//如果信号没有参数,槽函数也不能有参数,即槽函数参数<=信号参数
connect(p,&QPushButton::pressed,this,&Widget::print);
}
void Widget::print()
{
qDebug()<<"你点击了按钮";
}
Widget::~Widget()
{
}
//sonwidget.h
#ifndef SONWIDGET_H
#define SONWIDGET_H
#include
#include
class SonWidget : public QWidget
{
Q_OBJECT
public:
explicit SonWidget(QWidget *parent = nullptr);
QPushButton *button2;
signals:
void show_signal();
public slots:
void emitMySignal();
};
#endif // SONWIDGET_H
//sonwidget.cpp
#include "sonwidget.h"
SonWidget::SonWidget(QWidget *parent) : QWidget(parent)
{
this->setWindowTitle("子窗口");
this->resize(300,300);
button2 = new QPushButton("隐藏子窗口,显示父窗口",this);
connect(button2,&QPushButton::clicked,this,&SonWidget::emitMySignal);
}
void SonWidget::emitMySignal()
{
emit show_signal();
}
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include "sonwidget.h"
#include
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
SonWidget *sonwidget;
QPushButton *button1;
public slots:
void buttonHide();
void buttonShow();
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
this->setWindowTitle("父窗口");
this->resize(400,400);
this->sonwidget = new SonWidget;
sonwidget->show();
button1 = new QPushButton("隐藏父窗口,显示子窗口",this);
connect(button1,&QPushButton::clicked,this,&Widget::buttonHide);
connect(sonwidget,&SonWidget::show_signal,this,&Widget::buttonShow);
}
void Widget::buttonHide()
{
this->hide();
this->sonwidget->show();
}
void Widget::buttonShow()
{
this->show();
this->sonwidget->hide();
}
Widget::~Widget()
{
}
C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。首先看一下Lambda表达式的基本构成:
[capture](parameters) mutable->return-type
{
statement
}
[函数对象参数](操作符重载函数参数)mutable->返回值{函数体}
connect(zt,SIGNAL(hungry(QString)),st,SLOT(treat(QString)));
这里使用了 SIGNAL和 SLOT 这两个宏,将两个函数名转换成了字符串。注意到connect()函数的signal和slot都是接受字符串,一旦出现连接不成功的情况,Qt4是没有编译错误的(因为一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增加程序的不稳定性。
Qt5 在语法上完全兼容 Qt4,而反之是不可以的。