1. 概念
信号槽指的是信号函数和槽函数,这是Qt在C++的基础上新增的特性,可以非常容易地实现Qt对象之间的通信。
实际上信号槽就是一种代码上的“约定”,在代码编写时指定某种前提条件和达到条件需要执行的代码,在代码运行中如果触发的前提条件就执行预设的代码,如果没有触发前提条件就不执行预设的代码。
使用信号槽需要有两个先决条件:
● 通信的对象必须是继承自QObject类,QObject类是Qt所有类型的基类。
● 类中要有Q_OBJECT宏
2. 信号槽连接
2.1 函数原型
信号函数与槽函数的使用,需要建立连接,这就是之前说的“约定”。
连接函数如下所示。
参数1:发射者,是前提条件中名词对应的对象。
参数2:信号函数,是前提条件中动词对应的函数,此函数属于发射者所有,信号函数通常使用过去时。信号函数需要使用SIGNAL()包裹。
参数3:接收者,是达到条件后执行代码的主体,也是名词对应的对象。
参数4:槽函数,是达到条件后执行动作对应动词函数,此函数属于接收者所有,槽函数通常使用现在时。槽函数需要使用SLOT()包裹。
为了讲解方便,把信号槽的连接分为三类:
2.2 自带信号→自带槽
【例子】点击按钮,关闭窗口。
分析:发射者——按钮对象
信号函数——clicked函数
接收者——窗口对象
槽函数——close函数
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton* btn;
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(400,400);
btn = new QPushButton("关闭",this);
btn->move(200,200);
// 建立信号槽连接
// 发射者——按钮对象
// 信号函数——clicked函数
// 接收者——窗口对象
// 槽函数——close函数
connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}
Dialog::~Dialog()
{
delete btn;
}
2.3 自带信号→自定义槽
实际开发过程中,触发的代码功能繁多,Qt源代码不可能囊括所有的情况,因此槽函数可以自定义,这是使用的最多的是一种方式。
槽函数本质是一种特殊的成员函数。
【例子】点击按钮,向右且向下移动窗口,并输出当前窗口的位置坐标。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
#include <QDebug>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton *btn;
// 1. 声明槽函数
private slots: // 槽函数权限
void mySlot();
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(400,400);
btn = new QPushButton("自定义槽",this);
btn->move(150,200);
// 连接信号槽
// 如果判断不出来发射者或接收者,就先判断信号函数和槽函数
connect(btn,SIGNAL(clicked()),
this,SLOT(mySlot()));
}
// 2. 定义槽函数
void Dialog::mySlot()
{
// 3. 实现槽函数的内容
// 先获得当前坐标
int x = this->x();
int y = this->y();
x += 10;
y += 10;
// 移动当前坐标移动窗口
move(x,y);
// 输出当前坐标
qDebug() << x << y;
}
Dialog::~Dialog()
{
delete btn;
}
2.4 自定义信号
自定义信号主要用于后续一些相对复杂的特殊情况,目前所学知识没有完全适配的例子,因此本节的例子并不是问题的最优解。
【例子】点击按钮,关闭窗口。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QPushButton>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton *btn;
private slots:
void mySlot(); // 自定义槽函数
// 声明自定义信号函数,无权限
// 信号函数没有定义只有声明
signals:
void mySignal();
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(600,600);
btn = new QPushButton("自定义信号",this);
btn->move(200,200);
// 连接第一个信号槽
connect(btn,SIGNAL(clicked()),
this,SLOT(mySlot()));
// 连接第二个槽函数
connect(this,SIGNAL(mySignal()),
this,SLOT(close()));
}
void Dialog::mySlot()
{
// 发射自定义信号
emit mySignal();
}
Dialog::~Dialog()
{
delete btn;
}