【Qt开发】信号和槽

信号和槽

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

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

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

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

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

connect(sender,SIGNAL(信号(参数类型)),receiver,SLOT(槽函数(参数类型)));

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


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

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

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

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


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

QMetaObject::Connect QObject::connect
(
	const QObject *sender
	,const char *signal
	,const char *method
	,Qt::ConnectionType type = Qt::AutoConnection
)

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

connect(sender,SIGNAL(信号(参数类型)),SLOT(槽函数(参数类型)));

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

signals:
	void clicked(bool);
	void clicked();
private slots:
	void do_click(bool);
	void do_click();
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)解除与一个发射者所有信号的连接:

disconnect(myObject,nullptr,nullptr,nullptr);//静态函数形式
myObject->disconnect();//成员函数形式

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

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

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

disconnect(myObject,nullptr,myReceiver,nullptr);//静态函数形式
myObject->disconnect(myReceiver);//成员函数形式

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

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

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

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

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

void Widget::do_cilched()
{
	QPushButton *btn=qobject_cast<QPushButton *>(sender());
}

四、自定义信号及其使用

自定义信号

class My :public QObject
{
	Q_OBJECT

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

发射信号

//发射信号
emit hello();

编写槽函数

class Your :public QObject
{
	Q_OBJECT

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

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

My m1;
Your y1;
connect(m1,&My::hello,y1,&Your::world);

自定义信号和槽函数规则

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

信号和槽的使用

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

四、信号和槽的优缺点

优点

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

缺点

  • 运行时错误:信号与槽机制在编译时并不会检查连接的有效性,只有在运行时才能发现连接错误。如果信号或槽的名称拼写错误,或者参数不匹配,会导致程序在运行时出错
  • 性能开销:相比于直接函数调用,信号与槽机制可能会带来一定的性能开销。但对于大多数应用来说,这种开销是可以接受的
  • 复杂性:在大型应用中,如果信号与槽的连接过于复杂,可能会导致程序的逻辑变得难以理解。因此,适当的使用和组织信号与槽是重要的
  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
QT中,信号(Signals and Slots)是一种用于实现对象之间通信的机制。通过信号机制,可以将一个对象的动作或状态变化传递给其他对象进行相应的处理。以下是QT中使用信号的程序开发流程: 1. 定义信号: - 在需要发送信号的类中,使用`signals`关键字声明信号,并定义信号的参数列表。例如:`signals: void mySignal(int value);` - 在需要接收信号的类中,使用`slots`关键字声明函数,并定义函数的参数列表和返回值类型。例如:`public slots: void mySlot(int value);` 2. 连接信号: - 在需要连接信号的地方,使用`connect`函数进行连接。例如:`connect(sender, SIGNAL(mySignal(int)), receiver, SLOT(mySlot(int)));` - `sender`表示发送信号的对象,`SIGNAL(mySignal(int))`表示发送的信号,`receiver`表示接收信号的对象,`SLOT(mySlot(int))`表示接收的函数。 3. 发射信号: - 在发送信号的地方,通过调用`emit`关键字加上信号名和参数列表来发射信号。例如:`emit mySignal(value);` 4. 函数处理: - 当信号被发射时,与之连接的函数会被自动调用,并将信号的参数传递给函数进行处理。 需要注意的是,信号的连接可以在任何地方进行,但通常会在对象的构造函数或初始化函数中进行连接。 通过使用信号机制,可以实现对象之间的灵活通信,从而实现事件的处理、界面更新、数据传递等功能。这种机制在QT中被广泛应用,可以提高程序的可维护性和扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世_生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值