目录
1.信号槽的概念**
2.信号槽的连接***
2.1自带信号 → 自带槽
2.2 自带信号 → 自定义槽
2.3 自定义信号
3. 参数传递**
3.1 全局变量
3.2 信号槽传参
4. 对应关系**
4.1 一对多
4.2 多对一
1.信号槽的概念**
信号槽指的是信号函数与槽函数的连接,可以使用不同的对象通过信号槽连接在一起,从而实现对象之间的通信。
可以把信号槽的连接认为是对象之间的一种约定:如果.......,则.......
信号槽是Qt新增的特性,C++是不支持的,使用信号槽的前提条件:
1)通信的对象的类中要有Q_OBJECT宏
2)通信的对象必须继承自(包括间接继承)自QObject 【所以Qt对象的基类】类
2.信号槽的连接***
信号槽是一种约定,主要通过以下实现
// 参数1:信号发射者 是一个名词,因果关系中的因,表示发射信号函数的对象
// 参数2:信号函数的名称 是一个动词,需要使用SINGNAL()包裹,因果关系的因,表示动作
// 参数3:信号接收者 是一个名称,因果关系中的果,表示执行动作(操作函数)的对象
// 参数4:槽函数的名称 是一个动词,需要使用SLOT()包裹,因果关系中的果,表示动作
QObject::connect(const QObject * sender,
const char * signal,
const QObject * receiver,
const char * method) [static]
依次通过三种方式讲解信号槽的连接
1)自带信号→自带槽
2)自带信号→自定义槽
3)自定义信号→自带/自定义槽
2.1自带信号 → 自带槽
这是最简单的一种信号槽连接方式,因为信号函数和槽函数都在Qt源代码中实现了,只需要查询文档找到名称手动连接即可。
【例子】点击按钮,关闭窗口
分析:
参数1:按钮对象
参数2:点击信号
参数3:窗口对象
参数4:关闭槽
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include
#include
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton* btn;
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(400,400);
btn = new QPushButton("关",this);
btn->move(200,200);
// 连接信号槽
// 参数1:按钮对象
// 参数2:点击信号 clicked
// 参数3:窗口对象
// 参数4:关闭槽 close
connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}
Dialog::~Dialog()
{
delete btn;
}
2.2 自带信号 → 自定义槽
当槽函数完成的功能比较复杂时,Qt的源代码无法完全覆盖这样的功能,此时需要程序员手动写一个槽函数,并实现和连接。
需要注意的是槽函数实际上是一种特殊的成员函数。
【例子】点击按钮,把窗口向右下角移动,并输出当前的窗口坐标。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include
#include
#include
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton* btn;
// 声明自定义槽函数
private slots:
void mySlot();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(400,400);
btn = new QPushButton("关",this);
btn->move(200,200);
// 连接信号槽
// 参数1:按钮对象
// 参数2:点击信号 clicked
// 参数3:this
// 参数4:自定义槽函数mySlot
connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}
// 定义槽函数
void Dialog::mySlot()
{
// 先获得当前窗口的坐标
int x = this->x();
int y = this->y();
// 移动窗口
move(x+10,y+10);
// 输出当前坐标值
qDebug() << this->x() << this->y();
}
Dialog::~Dialog()
{
delete btn;
}
2.3 自定义信号
自定义信号主要用户后期一些特殊的情况,目前还没发举例,因此基于下面的案例,强行使用,并不是问题的最优解。
需要注意的是,信号函数没有权限,只有声明没有定义。不能调用信号函数,只能发射信号函数。
【例子】点击按钮,关闭窗口。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include
#include
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
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(500,500);
btn = new QPushButton("关闭",this);
btn->move(250,250);
// 连接第一个信号槽
connect(btn,SIGNAL(clicked()),
this,SLOT(mySlot()));
// 连接第二个槽函数
connect(this,SIGNAL(mySignal()),
this,SLOT(close()));
}
// 定义槽函数
void Dialog::mySlot()
{
// 发射自定义信号函数
emit mySignal();
}
Dialog::~Dialog()
{
delete btn;
}
3. 参数传递**
3.1 全局变量
可以借助一个全局(根据实际应用的范围来指定)可访问的变量来实现。
【例子】点击按钮,按钮上显示点击的次数。
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;
// 计数变量
int count;
// 自定义槽函数
private slots:
void mySlot();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
count = 0; // 赋予初始值
resize(400,400);
btn = new QPushButton("0",this);
//btn->move(200,200);
btn->setGeometry(150,150,50,50);
// 连接信号槽
connect(btn,SIGNAL(clicked()),
this,SLOT(mySlot()));
}
void Dialog::mySlot()
{
// 计数+1
count++;
// int → QString
// QString QString::number(int n) [static]
QString text = QString::number(count);
// 设置按钮的新文字
btn->setText(text);
}
Dialog::~Dialog()
{
delete btn;
}
运行结果:
3.2 信号槽传参
本节强行使用信号槽传参,此方法主要用于后续复杂问题的解决。
【例子】点击按钮,按钮上显示点击的次数。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include
#include
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton* btn;
int count = 0; // 计数
private slots:
void mySlot1(); // 自定义槽函数1
void mySlot2(int); // 自定义槽函数2
signals:
// 自定义信号槽,带参数!!!
void mySignal(int);
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(400,400);
btn = new QPushButton("0",this);
btn->move(200,200);
// 第一个信号槽连接
connect(btn,SIGNAL(clicked()),
this,SLOT(mySlot1()));
// 第二个信号槽的连接
connect(this,SIGNAL(mySignal(int)),
this,SLOT(mySlot2(int)));
}
void Dialog::mySlot1()
{
// 增加计数
count++;
// 发射自定义信号
emit mySignal(count);
}
void Dialog::mySlot2(int count)
{
// int → QString
QString text = QString::number(count);
// 更新显示
btn->setText(text);
}
Dialog::~Dialog()
{
delete btn;
}
需要注意的是:
- 理论上可以通过信号槽传递任意多个参数。
- 信号的参数个数必须大于等于槽的参数个数。
- 参数类型必须匹配。
4. 对应关系**
4.1 一对多
同一个信号可以连接多个槽函数。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include
#include
#include
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton *btn1;
QPushButton *btn2;
private slots:
void mySlot1();
void mySlot2();
void mySlot3();
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(300,400);
btn1 = new QPushButton("一对多",this);
btn1->move(100,200);
// 一对多
connect(btn1,SIGNAL(clicked()), this,SLOT(mySlot1()));
connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot2()));
//disconnect(btn1,SIGNAL(clicked()),this,SLOT(mySlot2()));
btn2 = new QPushButton("一对多",this);
btn2->move(100,250);
connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot3()));
}
void Dialog::mySlot1()
{
qDebug() << "A";
}
void Dialog::mySlot2()
{
qDebug() << "B";
}
void Dialog::mySlot3()
{
// 槽函数也是成员函数,直接调用mySlot1和2
mySlot1();
mySlot2();
}
Dialog::~Dialog()
{
delete btn1;
delete btn2;
}
4.2 多对一
多个信号也可以连接同一个槽函数,代码略。