【信号与槽机制】


在这里插入图片描述

🌟 信号函数

信号是一种特殊的成员函数,用于在特定事件发生时发出通知。一个类可以定义一个或多个信号,并在适当的时候发射(emit)这些信号。信号通常声明为 signals 关键字的一部分。

  • 范例:
    MyPushButton是一个自定义按钮控件类,继承于QPushButton。
class MyPushButton : public QPushButton
{
    Q_OBJECT
	explicit  MyPushButton(QWidget *parent = nulltpr);
signals://声明信号关键字
	//点击信号,是Qt预定义提供的信号
    void clicked();
    //发送按钮名称信号,自定义的信号
	void sendBtnNameSignal(const QString &btnName);
};
  • 发信号需要使用一个关键字:emit
void MyPushButton::MyPushButton(QWidget *parent)
	: QPushButton(parent)
{
	emit sendBtnNameSignal("btn");//在构造中发出发送按钮名称信号
}

🌟 槽函数

槽是普通的成员函数,用于响应信号。槽函数的特殊之处在于它们可以连接到一个或多个信号,以便在相关的信号被发射时被调用。

  • 范例:
    MyTextEdit是一个自定义富文本编辑控件类,继承于QTextEdit。
class MyTextEdit: public QTextEdit
{
    Q_OBJECT
//slots:是声明槽函数的关键字,public slots:表明这个一个公有成员槽函数
public slots:
	void SetBtnNameSlot(const QString &btnName);//设置按钮名称槽函数
};

🌟 连接函数

设置完信号函数和槽函数之后,它们还无法进行信息传递,还需要添加一个connect()函数,连接这两个不同类的成员函数。

  • 范例:
    MyWidget是一个自定义界面类,继承于QWidge。我在其中定义了一个MyPushButton 类和一个MyTextEdit类。
class MyPushButton;
class MyTextEdit;
class MyWidget: public QWidge
{
    Q_OBJECT
	explicit MyWidget(QWidge *parent = nullptr){
		m_btn = new MyPushButton();
		m_text = new MyTextEdit();
		//前提:是QObject的子类,上一篇blog已经说过原因。
		//connec函数连接信号函数和槽函数
		connect(m_btn,&MyPushButton::sendBtnNameSignal,
			m_text,&MyTextEdit::SetBtnNameSlot,Qt::UniqueConnection);
	}
private :
	MyPushButton *m_btn = nullptr;
	MyTextEdit *m_text = nullptr;
};

通过设置连接函数,两个不同对象中的成员函数得以进行消息传递。

🌸 QObejct::connect函数剖析

✨函数原型:

[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

通过传入指向发送者对象的指针和该对象的信号函数的地址以及指向接收者对象的指针和该对象的槽函数地址。

  • 通常,可以使用SIGNAL宏和SLOT宏将信号、槽函数包起来,这种写法要求至少写出信号函数和槽函数的传参类型。
  • 一个信号可以连接多个槽函数,同样,一个槽函数可以连接多个信号函数。
  • connect函数本身是线程安全的,但考虑到可能存在复杂的多线程环境,应当谨慎处理对象生存周期、跨线程连接和多线程并发访问等问题。
  • 关于第五个参数Qt::ConnectionType,缺省情况下会使用Qt::AutoConnection.这个参数决定了接收到信号后是立即执行槽函数,还是排队执行槽函数。
ConnectionType				  Value 			Description
Qt::AutoConnection 				0				(默认值)如果接收器存放在发出信号的线程中,则使用QT :: DirectConnection。否则,使用QT :: QueuedConnection。发射信号时确定连接类型。
Qt::DirectConnection			1				槽函数会在信号发出被响应时立即执行,并且,槽函数会被放在信号线程中执行。
Qt::QueuedConnection			2				当信号发射时,槽函数的调用请求会被放入接收对象所在线程的事件队列中,等待事件循环处理。适用于跨线程通信。
Qt::BlockingQueuedConnection	3				与qt :: QueuedConnection相同,只是信号函数会阻塞直到槽函数返回。如果接收者对象和发送者对象在同一个线程中,则不得使用此连接,否则应用程序将死锁。
Qt::UniqueConnection			0x80			用于确保信号与槽之间的连接是唯一的。如果已经存在相同的信号与槽连接,再次使用 Qt::UniqueConnection 连接时,连接操作将会失败,从而避免建立重复的连接
  • 如果在消息传递时使用了自定义的数据类型,需要先将该类型注册到元对象系统中,否则connect会失败。
//注册QVector<AgendaInfo>到元类型中
qRegisterMetaType<QVector<AgendaInfo>>("QVector<AgendaInfo>");

✨函数原型:

[static] QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
  • 这个函数原型中,支持将信号发送给一个QObejct的类的成员函数,并且在连接时无需列出函数的传参类型,Qt会为你去做检查的工作。
  • 因此,这个函数原型可以支持将匿名函数(lambda)作为连接的槽函数。
 QObject::connect(socket, &QTcpSocket::connected, this, [=] () {
          socket->write("GET " + page + "\r\n");
      }, Qt::AutoConnection);
  • Note: Qt::UniqueConnections do not work for lambdas, non-member functions and functors; they only apply to connecting to member functions.[译文]:Qt::UniqueConnections 这种连接方式不支持用于连接槽函数为匿名函数、非成员函数,connect函数会报错。

🌟 官方文档中给出的定义

📘Signals and slots are used for communication between objects. The signals and slots mechanism is a central feature of Qt and probably the part that differs most from the features provided by other frameworks. Signals and slots are made possible by Qt's meta-object system. 📖[译文]:信号和插槽用于对象之间的通信。信号和插槽机制是QT的主要特征,可能是与其他框架提供的功能不同的部分。信号和插槽通过QT的元对象系统使其成为可能。

🌟《Qt 5.9 C++开发指南》中的定义

️Qt 使用信号与槽的机制实现对象间通信,它隐藏了复杂的底层实现,完成信号与槽的关联后,发射信号时并不需要知道Qt是如何找到槽函数的。Qt信号与槽机制与 Delphi 和 C++ Builder 的“事件一一响应” 较类似,但是更加灵活。
某些开发架构使用回调函数(callback)实现对象间通信。与回调函数相比,信号与槽的执行速度稍微慢 ,因为需要查找连接的对象和槽函数 ,但是这种区别在应用程序运行时是感觉不到的,而其提供的灵活性却比回调函数强很多。

在这里插入图片描述

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

葛狂的博客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值