【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. 一个信号可以连接另一个信号

四、信号和槽的优缺点

优点

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

缺点

  • 运行时错误:信号与槽机制在编译时并不会检查连接的有效性,只有在运行时才能发现连接错误。如果信号或槽的名称拼写错误,或者参数不匹配,会导致程序在运行时出错
  • 性能开销:相比于直接函数调用,信号与槽机制可能会带来一定的性能开销。但对于大多数应用来说,这种开销是可以接受的
  • 复杂性:在大型应用中,如果信号与槽的连接过于复杂,可能会导致程序的逻辑变得难以理解。因此,适当的使用和组织信号与槽是重要的
相关推荐
学步_技术几秒前
Python编码系列—Python抽象工厂模式:构建复杂对象家族的蓝图
开发语言·python·抽象工厂模式
wn53124 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
Hello-Mr.Wang36 分钟前
vue3中开发引导页的方法
开发语言·前端·javascript
救救孩子把39 分钟前
Java基础之IO流
java·开发语言
WG_1740 分钟前
C++多态
开发语言·c++·面试
宇卿.1 小时前
Java键盘输入语句
java·开发语言
Amo Xiang1 小时前
2024 Python3.10 系统入门+进阶(十五):文件及目录操作
开发语言·python
friklogff1 小时前
【C#生态园】提升C#开发效率:深入了解自然语言处理库与工具
开发语言·c#·区块链
重生之我在20年代敲代码2 小时前
strncpy函数的使用和模拟实现
c语言·开发语言·c++·经验分享·笔记
爱上语文2 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring