信号与槽
Qt官网文档:Signals & Slots
信号
对象的内部状态以某种方式发生变化时,对象会发出信号。当发出信号时,与信号关联的槽函数通常会立即执行,就像正常的函数调用一样。发生这种情况时,信号和槽机制完全独立于任何GUI事件循环。一旦槽函数返回,将执行 emit(信号发射) 语句后面的代码。当使用队列时,emit 关键字后面的代码将继续,稍后再执行槽函数。
槽
槽就是对信号响应的函数,也称为槽函数。槽函数本身就是一个C++函数,可以定义在类的任何访问等级里,与一般函数不同的是:槽函数可以与信号关联。
可视化关联信号与槽
使用Qt组件预定义的信号和预定义的槽
在设计界面中的Signals & Slots Editor中,可以通过图形界面进行添加信号与槽的关联,在选择发送者和接收者后,就可以选择对应组件已经预定义好的信号和槽。
在Signals & Slots Editor添加关联后,mainwindow.ui(UI文件)会包含对应的内容,之后构建项目生成的ui_mainwindow.h中,会有一条将信号与槽的关联起来的代码。
QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close()));
生成空的槽函数
在设计界面中,对需要响应信号的组件进行操作:右键 -》 转到槽 -》 选择需要的信号。
在完成上述操作之后,会自动增加一个槽函数声明以及一个空的槽函数定义,我们就可以写入对应要响应的代码。
// 此处操作的组件objectName为pushButton_2
// .h
private slots:
void on_pushButton_2_clicked();
// .cpp
void MainWindow::on_pushButton_2_clicked()
{
}
这种方式不是通过直接添加connect()进行关联。而是通过connectSlotsByName()进行关联,该函数是在ui_mainwindow.h调用的。
// 函数声明
static void connectSlotsByName(QObject *o);
// ui_mainwindow.h调用
QMetaObject::connectSlotsByName(MainWindow);
connectSlotsByName()以递归方式搜索给定对象的所有子对象,并将它们的信号与函数名称遵循以下格式的槽函数(该函数对象存在的前提)进行关联:
void on_<object name>_<signal name>(<signal parameters>);
使用代码关联信号与槽
使用QObject::connect()来实现信号与槽的关联。
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);
static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection);
inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
const char *member, Qt::ConnectionType type = Qt::AutoConnection) const;
sender是发射信号的对象,signal()是信号函数,receiver是接收信号的对象,slot()是槽函数。
// connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(pushButton_2_clicked()));
SLOT和SIGNAL的定义在qobjectdefs.h中,将参数转换成字符串,用于指明信号和槽。
# define SLOT(a) "1"#a
# define SIGNAL(a) "2"#a
由于没有通过可视化来添加信号与槽的关联,所以槽函数的声明和定义也是需要手动进行添加的。
// mainwindow.h, 添加槽函数声明
private slots:
void pushButton_2_clicked();
// mainwindow.cpp, 添加槽函数定义
void MainWindow::pushButton_2_clicked()
{
}