什么是Qt的Signals和Slots?

您所在的位置:网站首页 变量variable和信号signal有什么区别 什么是Qt的Signals和Slots?

什么是Qt的Signals和Slots?

2023-05-14 07:07| 来源: 网络整理| 查看: 265

Signals & Slots

Signals & Slots

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

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.Introduction

在 GUI 编程中,当我们更改一个小部件时,我们经常希望通知另一个小部件。 更一般地说,我们希望任何类型的对象都能够相互通信。 例如,如果用户单击关闭按钮,我们可能希望调用窗口的 close() 函数。 其他工具包使用回调实现这种通信。 回调是指向函数的指针,因此如果您希望处理函数通知您某个事件,您可以将指向另一个函数(回调)的指针传递给处理函数。 然后,处理函数会在适当的时候调用回调。 虽然确实存在使用此方法的成功框架,但回调可能不直观,并且可能在确保回调参数的类型正确性方面遇到问题。

In GUI programming, when we change one widget, we often want another widget to be notified. More generally, we want objects of any kind to be able to communicate with one another. For example, if a user clicks a Close button, we probably want the window's close() function to be called. Other toolkits achieve this kind of communication using callbacks. A callback is a pointer to a function, so if you want a processing function to notify you about some event you pass a pointer to another function (the callback) to the processing function. The processing function then calls the callback when appropriate. While successful frameworks using this method do exist, callbacks can be unintuitive and may suffer from problems in ensuring the type-correctness of callback arguments.Signals and Slots

在 Qt 中,我们有一个回调技术的替代方案:我们使用信号和槽。 当特定事件发生时会发出信号。 Qt 的小部件有许多预定义的信号,但我们总是可以子类化小部件以向它们添加我们自己的信号。 插槽是响应特定信号而调用的函数。 Qt 的小部件有许多预定义的插槽,但通常的做法是子类化小部件并添加自己的插槽,以便您可以处理您感兴趣的信号。

In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal. Qt's widgets have many pre-defined slots, but it is common practice to subclass widgets and add your own slots so that you can handle the signals that you are interested in.

信号和槽机制是类型安全的:信号的签名必须与接收槽的签名匹配。 (事实上,一个槽的签名可能比它接收的信号更短,因为它可以忽略额外的参数。)由于签名是兼容的,编译器可以帮助我们在使用基于函数指针的语法时检测类型不匹配。 基于字符串的 SIGNAL 和 SLOT 语法将在运行时检测类型不匹配。 信号和槽是松散耦合的:发出信号的类既不知道也不关心哪个槽接收信号。 Qt 的信号和槽机制确保如果将信号连接到槽,则将在正确的时间使用信号的参数调用槽。 信号和槽可以接受任意数量的任意类型的参数。 它们是完全类型安全的。

The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.) Since the signatures are compatible, the compiler can help us detect type mismatches when using the function pointer-based syntax. The string-based SIGNAL and SLOT syntax will detect type mismatches at runtime. Signals and slots are loosely coupled: A class which emits a signal neither knows nor cares which slots receive the signal. Qt's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take any number of arguments of any type. They are completely type safe.

从 QObject 或其子类之一(例如 QWidget)继承的所有类都可以包含信号和槽。当对象以可能对其他对象感兴趣的方式改变其状态时,信号由对象发出。这就是对象进行通信的全部内容。它不知道也不关心是否有任何东西在接收它发出的信号。这是真正的信息封装,并确保对象可以用作软件组件。槽可以用来接收信号,但它们也是普通的成员函数。就像一个对象不知道是否有任何东西接收到它的信号一样,一个槽也不知道它是否有任何信号连接到它。这确保了可以使用 Qt 创建真正独立的组件。您可以将任意数量的信号连接到单个插槽,并且可以将信号连接到任意数量的插槽。甚至可以将一个信号直接连接到另一个信号。 (这将在第一个信号发出时立即发出第二个信号。)信号和槽一起构成了一个强大的组件编程机制。

All classes that inherit from QObject or one of its subclasses (e.g., QWidget) can contain signals and slots. Signals are emitted by objects when they change their state in a way that may be interesting to other objects. This is all the object does to communicate. It does not know or care whether anything is receiving the signals it emits. This is true information encapsulation, and ensures that the object can be used as a software component. Slots can be used for receiving signals, but they are also normal member functions. Just as an object does not know if anything receives its signals, a slot does not know if it has any signals connected to it. This ensures that truly independent components can be created with Qt. You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need. It is even possible to connect a signal directly to another signal. (This will emit the second signal immediately whenever the first is emitted.) Together, signals and slots make up a powerful component programming mechanism.Signals

当对象的内部状态以某种可能对对象的客户端或所有者感兴趣的方式发生变化时,对象会发出信号。 信号是公共访问函数,可以从任何地方发出,但我们建议只从定义信号的类及其子类中发出它们。 当一个信号发出时,连接到它的槽通常会立即执行,就像一个普通的函数调用一样。 发生这种情况时,信号和槽机制完全独立于任何 GUI 事件循环。 一旦所有槽都返回,将在发出语句之后执行代码。 使用排队连接时情况略有不同; 在这种情况下,emit 关键字后面的代码将立即继续执行,而 slot 将在稍后执行。

Signals are emitted by an object when its internal state has changed in some way that might be interesting to the object's client or owner. Signals are public access functions and can be emitted from anywhere, but we recommend to only emit them from the class that defines the signal and its subclasses. When a signal is emitted, the slots connected to it are usually executed immediately, just like a normal function call. When this happens, the signals and slots mechanism is totally independent of any GUI event loop. Execution of the code following the emit statement will occur once all slots have returned. The situation is slightly different when using queued connections; in such a case, the code following the emit keyword will continue immediately, and the slots will be executed later.

如果多个槽连接到一个信号,则在发出信号时,这些槽将按照它们连接的顺序一个接一个地执行。 信号由 moc 自动生成,不得在 .cpp 文件中实现。 他们永远不能有返回类型(即使用 void)。 关于参数的注释:我们的经验表明,如果信号和槽不使用特殊类型,则它们的可重用性更高。 如果 QScrollBar::valueChanged() 使用特殊类型,例如假设的 QScrollBar::Range,它只能连接到专门为 QScrollBar 设计的槽。 将不同的输入小部件连接在一起是不可能的。

If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted. Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void). A note about arguments: Our experience shows that signals and slots are more reusable if they do not use special types. If QScrollBar::valueChanged() were to use a special type such as the hypothetical QScrollBar::Range, it could only be connected to slots designed specifically for QScrollBar. Connecting different input widgets together would be impossible.Slots

当一个连接到它的信号被发射时,一个槽被调用。 插槽是普通的C++函数,可以正常调用; 它们唯一的特点是可以将信号连接到它们。 由于槽是普通的成员函数,因此在直接调用时它们遵循普通的 C++ 规则。 但是,作为槽,它们可以被任何组件调用,无论其访问级别如何,都可以通过信号槽连接。 这意味着从任意类的实例发出的信号可能会导致在不相关类的实例中调用私有槽。 您还可以将插槽定义为虚拟的,我们发现这在实践中非常有用。

A slot is called when a signal connected to it is emitted. Slots are normal C++ functions and can be called normally; their only special feature is that signals can be connected to them. Since slots are normal member functions, they follow the normal C++ rules when called directly. However, as slots, they can be invoked by any component, regardless of its access level, via a signal-slot connection. This means that a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class. You can also define slots to be virtual, which we have found quite useful in practice.

与回调相比,信号和槽的速度稍慢,因为它们提供了更高的灵活性,尽管对于实际应用程序的差异并不显着。一般来说,发出一个连接到某些槽的信号,比直接调用接收器慢大约十倍,使用非虚拟函数调用。这是定位连接对象、安全地迭代所有连接(即检查后续接收器在发射期间是否被破坏)以及以通用方式编组任何参数所需的开销。虽然十个非虚拟函数调用听起来很多,但它比任何新操作或删除操作的开销要少得多。一旦你执行了一个字符串、向量或列表操作,在幕后需要 new 或 delete,信号和槽的开销只占整个函数调用成本的很小一部分。每当您在插槽中进行系统调用时,都是如此。或者间接调用十多个函数。信号和槽机制的简单性和灵活性非常值得您的用户甚至不会注意到的开销。请注意,定义称为信号或槽的变量的其他库在与基于 Qt 的应用程序一起编译时可能会导致编译器警告和错误。为了解决这个问题,#undef 有问题的预处理器符号。

Compared to callbacks, signals and slots are slightly slower because of the increased flexibility they provide, although the difference for real applications is insignificant. In general, emitting a signal that is connected to some slots, is approximately ten times slower than calling the receivers directly, with non-virtual function calls. This is the overhead required to locate the connection object, to safely iterate over all connections (i.e. checking that subsequent receivers have not been destroyed during the emission), and to marshall any parameters in a generic fashion. While ten non-virtual function calls may sound like a lot, it's much less overhead than any new or delete operation, for example. As soon as you perform a string, vector or list operation that behind the scene requires new or delete, the signals and slots overhead is only responsible for a very small proportion of the complete function call costs. The same is true whenever you do a system call in a slot; or indirectly call more than ten functions. The simplicity and flexibility of the signals and slots mechanism is well worth the overhead, which your users won't even notice. Note that other libraries that define variables called signals or slots may cause compiler warnings and errors when compiled alongside a Qt-based application. To solve this problem, #undef the offending preprocessor symbol.

Reference: https://doc.qt.io/qt-5/signalsandslots.html



【本文地址】


今日新闻


推荐新闻


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