【Qt开发】信号和槽

信号和槽

信号和槽

信号和槽是Qt的创新之一,实现了对象间的通信,它隐藏了复杂的底层实现。完成信号与槽函数的关联后,发送者并不关注此信号是否有关联的槽函数,关联的槽函数就会运行。

一、connect()函数的不同参数形式

静态函数QObject::connect()有很多参数形式,如下:

cpp 复制代码
QMetaObject::Connect QObject::connect
(
	const QObject *sender
	,const char *signal
	,const QObject  *receiver
	,const char *method
	,Qt::ConnectionType type = Qt::AutoConnection
)

使用这种参数形式的connect()函数进行信号和槽函数之间的连接,如下

cpp 复制代码
connect(sender,SIGNAL(信号(参数类型)),receiver,SLOT(槽函数(参数类型)));

这里使用宏SIGNAL()SLOT()来指定信号和槽函数,如果信号和槽函数有参数,还需要明确参数类型


cpp 复制代码
QMetaObject::Connect QObject::connect
(
	const QObject *sender
	,const QMetaMethod &signal
	,const QObject  *receiver
	,const QMetaMethod &method
	,Qt::ConnectionType type = Qt::AutoConnection
)

使用这种参数形式的connect()函数进行信号和槽函数之间的连接,如下

cpp 复制代码
connect(sender,&对象::信号,receiver,&对象::槽函数);
例如:
connect(sender,&QLineEdit::textChanged,receiver,&Widget::do_textChanged);

在信号和槽函数参数较多的情况下,采用这种参数形式的connect()函数来连接比较简单


还有一个作为QObject成员函数的connect(),其函数原型如下:

cpp 复制代码
QMetaObject::Connect QObject::connect
(
	const QObject *sender
	,const char *signal
	,const char *method
	,Qt::ConnectionType type = Qt::AutoConnection
)

这个函数里没有接收者参数,接收者就说对象自身,this表示窗口对象,槽函数是窗口类里定义的

cpp 复制代码
connect(sender,SIGNAL(信号(参数类型)),SLOT(槽函数(参数类型)));

当信号重载了,连接槽函数需要使用模板函数qOverload()来明确参数类型

cpp 复制代码
signals:
	void clicked(bool);
	void clicked();
private slots:
	void do_click(bool);
	void do_click();
cpp 复制代码
connect(sender,&对象::clicked,receiver,qOverload<bool>(&对象::do_click));
connect(sender,&对象::clicked,receiver,qOverload<>(&对象::do_click));

我们在设计槽函数的时候一般也不会设计成重载型的


connect()函数的最后一个参数:

  • Qt::AutoConnection(默认值):如果信号的发射者和接收者在同一个线程中,就使用Qt::DirectConnection方式,否则Qt::QueuedConnection方式。
  • Qt::DirectConnection:信号被发射时槽函数立即运行,槽函数与信号在同一个线程中。
  • Qt::QueuedConnection:在事件循环回到接收者线程后运行槽函数,槽函数与信号在不同的线程中。
  • Qt::BlockingQueuedConnection:与Qt::QueuedConnection相似,区别是信号线程会阻塞,知道槽函数运行完毕。当信号和槽函数在同一个线程中时,绝对不能使用这种方式,否则会被死锁。

二、disconnect()函数的使用

函数disconnect()用于解除信号和槽的连接,详细情况查看Qt帮助文档

1)解除与一个发射者所有信号的连接:

cpp 复制代码
disconnect(myObject,nullptr,nullptr,nullptr);//静态函数形式
myObject->disconnect();//成员函数形式

2)解除与一个特定信号的所有连接:

cpp 复制代码
disconnect(myObject,SIGNAL(信号()),nullptr,nullptr);//静态函数形式
myObject->disconnect(SIGNAL(信号()));//成员函数形式

3)解除与一个特点接收者的所有连接:

cpp 复制代码
disconnect(myObject,nullptr,myReceiver,nullptr);//静态函数形式
myObject->disconnect(myReceiver);//成员函数形式

4)解除特定的一个信号与槽的连接:

cpp 复制代码
disconnect(myObject,&对象::信号,myReceiver,&对象::槽函数);//静态函数形式

三、使用函数sender()获取函数的发射者

在槽函数调用函数sender()可以获取信号发射者的QObject对象指针,如果知道信号发射者的类型,我们就可以使用qobject_cast<>转化成确定类型对象的指针

例如:界面上有一个QPushButton按钮cilcked()信号的槽函数如下:

cpp 复制代码
void Widget::do_cilched()
{
	QPushButton *btn=qobject_cast<QPushButton *>(sender());
}

四、自定义信号及其使用

自定义信号

cpp 复制代码
class My :public QObject
{
	Q_OBJECT

signals:
	//自定义信号 hello
	void hello();
};

发射信号

cpp 复制代码
//发射信号
emit hello();

编写槽函数

cpp 复制代码
class Your :public QObject
{
	Q_OBJECT

private slot:
	//定义槽函数
	void world();
};

使用函数connect()连接信号hello()和槽world()

cpp 复制代码
My m1;
Your y1;
connect(m1,&My::hello,y1,&Your::world);

自定义信号和槽函数规则

  1. 信号函数必须是无返回值函数,但可以有参数
  2. 信号函数无需实现'
  3. 槽函数参数的个数不得大于信号函数参数是的个数,严格情况下,信号和槽函数的参数个数和类型需要保持一致
  4. 使用信号与槽的类中,必须在类的定义中插入宏Q_OBJECT

信号和槽的使用

  1. 一个信号可以连接多个槽函数
  2. 多个信号可以连接一个槽函数
  3. 一个信号可以连接另一个信号

四、信号和槽的优缺点

优点

  • 松耦合:信号和槽机制使得对象之间不需要显示的依赖关系,从而降低耦合独
  • 异步通信:发射者可以在不等待接收者的响应情况下继续执行,提高程序的响应性能
  • 事件驱动:图形化编程常常和事件处理有管,信号和槽的机制使得处理事件更加灵活、方便
  • 支持多线程
  • 可扩展性:通过信号与槽,可以轻松地扩展系统,添加新的功能模块,不需要修改现有代码,只需在适当的位置连接信号与槽

缺点

  • 运行时错误:信号与槽机制在编译时并不会检查连接的有效性,只有在运行时才能发现连接错误。如果信号或槽的名称拼写错误,或者参数不匹配,会导致程序在运行时出错
  • 性能开销:相比于直接函数调用,信号与槽机制可能会带来一定的性能开销。但对于大多数应用来说,这种开销是可以接受的
  • 复杂性:在大型应用中,如果信号与槽的连接过于复杂,可能会导致程序的逻辑变得难以理解。因此,适当的使用和组织信号与槽是重要的
相关推荐
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner3 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz8 天前
QML Hello World 入门示例
qt
xcyxiner11 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner12 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00615 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术15 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript