Signal & Slot 是QT语言的核心机制,Qt提供了信号与槽机制用于完成界面操作的响应,是完成任意两个Qt对象之间通信的机制。其中,信号会在某个特定情况或动作下被触发,槽是等同与接受并处理信号的函数。[1]
一、关于信号与槽的映射关系 信号与槽的映射关系用集合的关系无非是上面四种,一个信号可能指向多个处理信号的槽;一个槽也可能被多个信号关联。
最常见的形式。该函数参数依次是: 信号 信号字符指针 接收者 信号字符指针,QT使用宏(SLOT(XXX)
SIGNAL(XXX)
)的方式信号与槽(signals
public slots
private slots
),该宏可以将对应的信号与槽“声明”转换成适合的const char *
,宏接受的参数要求:
- 只能是信号与槽中的一种
- “声明”是忽略
void
的声明
QMetaObject::Connection QObject::connect(\
const QObject *sender, const char *signal, \
const QObject *receiver, const char *method,\
Qt::ConnectionType type = Qt::AutoConnection)
注意:
- 必须使用
SIGNAL
和SLOT
宏指定信号和方法 - 信号与方法是不带返回值的声明
- 信号还可连接到另一个信号
- 机制线程安全的
一个简单的例子:
QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
label, SLOT(setNum(int)));
2.2 QObject间signal&slot“成员函数指针形式”
该形式将原来const char *
位置的变成了信号或者槽成员函数指针。
QMetaObject::Connection connect(\
const QObject *sender, PointerToMemberFunction signal,\
const QObject *receiver, PointerToMemberFunction method,\
Qt::ConnectionType type = Qt::AutoConnection);
关于C++成员函数地址可以由以下方法获取:&A::fun
。其重载的优点在于:
- 解除了限制。形式一要求signal和method必须是类中的信号或者槽;
缺点在于:
- 重载时书写复杂。若signal或method若重载了,需要通过强制转换告知具体的重载方法
此外,我想提提内置控件信号与槽的命名方法,一般来说:
- 信号名是动作的过去式(pressed),槽则是动作原型或set+状态
如我们常用的QPushButton继承了来自QAbstractButton的信号与槽:
public Q_SLOTS:
void setIconSize(const QSize &size);
void animateClick(int msec = 100);
void click();
void toggle();
void setChecked(bool);
Q_SIGNALS:
void pressed();
void released();
void clicked(bool checked = false);
void toggled(bool checked);
如果你想自定义一个信号或者槽,你需要注意以下几点:
- 信号与槽都没有返回值
- 信号必须在头文件声明,且没有实现;
- 信号与槽的参数类型必须匹配或者可隐式转换;
- 信号可以多发信号,槽可以选择性接收(也就是信号参数大于或者等于槽的参数个数)
例子:
QObject::connect(qb1,&QPushButton::clicked,this,&MainWindow::fun);//fun是自定义的普通成员函数
QObject::connect(qb1,&QPushButton::clicked,this,&QPushButton::hide);//hide是内置的控件的slots
2.3 QObject signal 和函数对象
这种方法限制比方法二更加小,你甚至都不需要是类中的成员函数,只要求是一个函数对象。
QMetaObject::Connection
connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
Functor是函数对象,llambda就是其中一个,结合这个优点非常突出:
- 更加简洁。结合lambda,可以省略对QObject槽函数的书写;
- 更加灵活。结合lambdat替代QObject::sender();
- 提示灵活。使用形式一,我需要查阅文档才能知道内置控制有那些信号和槽,这种形式,使用
::
可以直接查看拥有的信号与槽。
缺点是:
- 重载麻烦甚至不能用
一个lambda对象例子:
QObject::connect(qb1,&QPushButton::clicked,this,[]{qDebug()
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?