Qt6入门教程 7:信号和槽机制(原理和优缺点)

您所在的位置:网站首页 爱立方教材的优缺点 Qt6入门教程 7:信号和槽机制(原理和优缺点)

Qt6入门教程 7:信号和槽机制(原理和优缺点)

2024-06-17 15:05| 来源: 网络整理| 查看: 265

目录

一.简介

二.信号和槽

1.信号和槽机制是类型安全的

2.信号和槽是松散耦合的

三.信号(signals)

四.槽(slots)

五.信号与槽的简单模拟

六.第三方信号槽实现

七.在Qt中使用第三方的Signals和Slots

八.总结一下优点和缺点

1.优点

2.缺点

信号和槽用于对象之间的通信。信号和槽机制是Qt的核心机制,也是Qt不同于其他框架的最突出的特征。Qt的元对象系统使信号和槽成为可能。

一.简介

在GUI编程中,当我们改变一个控件,通常希望其他控件被通知到。更一般的,我们希望任意对象之间能够通信。例如,如果我们点击了“关闭”按钮,我们希望窗口的close()函数被调用。 其他工具包使用回调来实现这种通信。回调函数是一个指向函数的指针,所以如果你想要一个处理函数通知你一些事件,你可以将一个指向另一个函数(回调函数)的指针传递给处理函数。处理函数然后在适当的时候调用回调函数。但回调可能不太直观,而且在确保回调参数的类型正确性方面可能会遇到问题。

二.信号和槽

在Qt中,我们有一个回调技术的替代方案:我们使用信号和槽。当特定事件发生时发出信号。Qt的控件有许多预定义的信号,但是我们总是可以子类化控件,添加一些自定义信号。槽(slots)是响应特定信号(signals)而调用的函数。Qt的控件有许多预定义的槽,但是通常的做法是子类化控件并自定义槽函数,这样就可以处理感兴趣的信号。 下图为信号与槽的关系图:支持一对多,多对一

1.信号和槽机制是类型安全的

信号与槽机制要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,信号的参数可以比槽函数的参数多,此时槽可以忽略多余参数。由于参数的一致性,所以当使用基于函子(functor-base)的信号与槽语法时,编译器可以帮助我们检测类型是否匹配(Qt5开始支持的语法);基于字符串(string-base)的信号和槽语法将在运行时检测类型不匹配(Qt4开始支持的语法)。

注:functor(函子)是C++编程语言中的一个概念,它允许将一个可调用对象(函数、函数指针、成员函数指针等)以及其相关的状态(变量、成员变量等)封装起来,形成一个对象,这个对象可以像函数一样被调用。

2.信号和槽是松散耦合的

信号和槽是松散耦合的,发出信号的类既不知道也不关心哪个槽接收信号。Qt的信号和槽机制确保,如果您将信号连接到槽,将在正确的时间使用信号的参数调用该槽。信号和槽可以采用任意数量的任何类型的参数。它们完全是类型安全的。 从QObject或其子类(例如QWidget)继承的所有类都可以包含信号和槽。当对象的状态发生变化时,它们会发出信号,它不知道或不关心是否有任何槽在接收它发出的信号,这足以实现信息封装。 槽可以用于接收信号,但它们也是正常的成员功能。就像一个对象不知道是否有任何其他对象接收到它的信号一样,槽也不知道它是否有任何信号连接到它。这确保了可以使用Qt创建真正独立的组件。 您可以将任意多个信号连接到一个槽,并且可以将信号连接到任意多个槽。甚至可以将一个信号直接连接到另一个信号。(每当发出第一个信号时,这将立即发出第二个信号。) 信号和槽共同构成了强大的组件编程机制。

三.信号(signals)

当对象内部状态以对象的客户端或用户感兴趣的某种方式发生变化时—比如点击、鼠标移动等,对象就会发出信号。信号(signals)都是共有(public)的,可以从任何地方发出,但最好只从该定义信号的类及其子类使用该信号。当信号发出时,通常采用直连方式连接槽函数,这种连接方式会立即执行槽函数,就像普通的函数调用一样。此时信号和槽机制完全独立于任何GUI事件循环。一旦所有的槽都返回,emit语句之后的代码就会执行(同步发送)。当使用队列连接时,情况略有不同;在这种情况下,emit关键字后面的代码将立即继续,槽将稍后执行(异步发送)。如果多个槽连接到一个信号,当信号发出时,槽将按照它们连接的顺序依次执行。信号是由moc(元对象编译器)自动生成的,在build目录中的moc_**文件中。信号永远不能有返回类型(即使用void)。

四.槽(slots)

槽在信号发出时被调用。槽也是C++函数,可以像普通函数一样正常调用,它们唯一的特点是可以连接信号。因为槽函数是普通的成员函数,所以当直接调用时,它们遵循普通的C++规则。与回调相比,信号和槽稍微慢一些,因为它们提供了更大的灵活性,尽管实际应用程序中的差异并不大。一般来说,emit一个连接到一些槽的信号,大约比直接调用非虚函数慢十倍。原因是在定位连接对象、安全遍历所有连接(即检查在发送过程中后续槽函数是否被销毁)等所需的开销。虽然十个非虚函数调用可能听起来很多,但它的开销比任何new或delete操作都要小得多。一旦在后续执行需要new或delete字符串、vector or list等操作,信号和槽开销只占整个函数调用开销的很小一部分。信号和槽机制的简单性和灵活性是非常值得的,用户甚至不会注意到这些开销。 注:当定义了signals或slots变量的第三方库与基于qt的应用程序一起编译时,可能会导致编译器警告和错误。要解决这个问题,请#undef有问题的预处理器符号

五.信号与槽的简单模拟 #include #include #include #include // 这里是以字符串“CaoShangPa”作为连接信号和槽的媒介 class Connections { public:     // 按名称建立映射关系     void connect(const std::string &name, const std::function &callback)     {         m_callbackMap[name] = callback;     }     // 按名称调用     void invoke(const std::string &name)     {         auto it = m_callbackMap.find(name);         if (it != m_callbackMap.end()) {             it->second();         }     } private:     std::map m_callbackMap; };   static Connections g_connections;   class Signal { public:     void send()     {         std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3