Qt Signals Slots Emit

Posted onby admin

Qt documentation states that signals and slots can be direct, queued and auto. It also stated that if object that owns slot 'lives' in a thread different from object that owns signal, emitting such signal will be like posting message - signal emit will return instantly and slot method will be called in target thread's event loop. 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.

Nd the index of the signal and of the slot Keep in an internal map which signal is connected to what slots When emitting a signal, QMetaObject::activate is called. It calls qt metacall (generated by moc) with the slot index which call the actual slot. Qt offers a new event handling system: signal-slot connections. Imagine an alarm clock. When alarm is ringing, a signal is being sent (emit). And you're handling it in a slot.

Author: Cao Qun
Original text: https://mp.weixin.qq.com/s/Mp…
Welcome to the official account of the technical team of the school network.

QT is a cross platform C + + GUI application development framework developed by QT company in 1991. It can be used to develop GUI programs as well as non GUI programs, such as console tools and servers. QT is an object-oriented framework. With special code generation extensions (called meta object compiler) and some macros, QT is easy to extend and allows real component programming. QT is a cross platform development framework, supporting windows, Linux, MacOS and other different platforms; QT has a large number of development documents and rich API, which brings great convenience to developers; QT users are more and more, and many excellent products are developed based on QT, such as WPS offic, opera browser, QT creator, etc. The core mechanism of QT is the signal and slot. Next, we analyze the implementation principle through the source code.

  • signalWhen an object changes its state, the signal is emitted by the object, and the object is only responsible for sending the signal, and it does not know who is receiving the signal on the other end.
  • groove: used to receive signals, and slots are just ordinary object member functions. A slot does not know if there is any signal connected to it.
  • Signal to slot connection: all classes derived from QObject or its subclasses, such as QWidget, can contain signals and slots. It is managed by static method: QObject:: connect (sender, signal (signal), receiver, slot (slot)); where sender and receiver are pointers to objects, and signal() and slot() are macros for converting signals and slots.
  • 1. First of all, we set up a good environment, such as installing qt5.7 (including source code) + vs2013 and corresponding plug-ins on Windows system. We mainly compile and debug through vs.
  • 2. We write a simple instance, build it, and copy the PDB of qtcore in the QT installation directory to our executable file directory, as shown in the following figure:

Here is the demo code we want to analyze:
// MainWindow.h

// MainWindow.cpp

We can create a QT project named demo, write the above code and build it. Under vs, we can import the QT project into a vs project, compile and generate it. The running results are as follows:

Qt Signals Slots Emit

Click the middle button to see the console print the following information:

Step 1: basic structure:

When we analyze the code, we can see that in the header files test and MainWindow classes, there are Q_ For macro like object, we can see an additional MOC under the executable folder above_ MainWindow.cpp Of course, what we can’t do after we try to build the macro and the signal slot after we try to build the macro and the signal? Let’s take a look at this macro:

It turns out that this macro is some static and virtual methods. But if we add it to a class and do not implement it, it will definitely report an error. Why can it run normally? It turns out that QT helps us to do a lot of things. Before the compiler compiles the QT code, QT first translates the syntax of QT’s own extension. This operation is accomplished through MOC (meta object compiler), also known as “meta object compiler”. First, the MOC will analyze the source code, including Q_ The header file of object is generated as a C + + source file. The name of this file will be the source file name followed by MOC_ After that, it is processed by the compiler together with the original file. Then we think that the CPP at the beginning of MOC must implement the methods in the macro above and the assignment of data. Next, let’s look at the MOC_ MainWindow.cpp This document:

As we can see from the code above, it’s for Q_ The static data in object are assigned values, and those methods are implemented. These are generated by QT’s MOC compiler for us. The code is analyzed, and symbols are generated for signals and slots, as well as specific data structures. The following mainly records the reference count, size and offset of classes, signals and slots, which will be used later.

Through QT_ MOC_ After the macro literal is replaced, the following data is obtained:

Let’s take a look at QT below_ meta_ data_ MainWindow array structure: content has two columns. The first column is the total number, and the second column is the index describing the beginning of the array, such as 1, 14, / / methods, indicating that there is a method. We can see that slots start from index 14.

From the top source code, we can see that signal and slot are used to correlate signals and slots. What are the functions of these two macros? Let’s analyze:

analysis:

From the above, we can see that these two are actually string concatenation macros, which will splice “2” in front of the signal, such as “2clean()”, and splice “1” in front of slots, such as “1onclean()”. Among them, qflaglocation mainly stores method in const char * locations [count] in flageddebugsignatures in qthreaddata; Table is used to locate the row information corresponding to the code.

After precompiling, it is as follows:

Through the introduction of some basic macros and data structures above, we know that QT has done a lot of work for us, helped us generate MOC code, provided us with some macros, so that we can develop succinctly and conveniently. Then, how does QT associate signals with slots, that is, two different examples, and how to communicate through the signaling slot mechanism? Next, let’s look at the implementation principle of signal and slot correlation

The second step is the correlation between signal and slot

  • 1. Check the string of signal and slot first, qsignal_ Code is 1; signal_ Code is 2.
  • 2. Get metadata (the same for sender and receiver).

This method is our upper MOC_ MainWindow.cpp Medium.

According to debugging, we can see QObject:: D_ PTR > metaobject is empty, so smeta is the static metaobject variable above.

//First of all, we have to understand the definition of qmetaobject and qmetaobjectprivate

In QT, in order to achieve binary compatibility, a private class is generally defined. Qmetaobjectprivate is the private class of qmetaobject. Qmetaobject is responsible for some interface implementation, and qmetaobjectprivate is specifically implemented. These two classes are generally accessed by P pointer and D pointer. There is a macro:

Let’s see that the static metaobject above is a variable of type qmetaobject, where qmetaobject is assigned a value:

  • 1) & QWidget:: staticmetaobject – > Superdata
  • 2)qt_meta_stringdata_Test.data -> stringdata
  • 3)qt_meta_stringdata_Test() -> data
  • 4)qt_ static_ Metacall (callback function) – > static_ metacall

Among them, qmetaobject is the external structure, and the connection method inside calls or implements the connect in qmetaobjectprivate. The D member in qmetaobject is filled with the static metaobject data above, while the member in qmetaobjectprivate is filled with QT_ meta_ stringdata_ For the data in the test array, we can see that the first 14 data are filled. This is also the reason why MOC takes 14 as the cardinal number when generating methoddata. The conversion method is as follows:

  • 3. Get and save the signal parameters and names. As follows, save the signal parameters and return the method name.
  • 4. Calculate indexes (including base classes).

The implementation is as follows:

Qt Signals Slots Emit Signal

Where int handle = priv (M > D.Data) – > methoddata + 5i. We can analyze that, in fact, it is 14 + 5i. So why five? Because:
// signals: name, argc, parameters, tag, flags
1, 0, 24, 2, 0x06 / Public /,
// slots: name, argc, parameters, tag, flags
3, 0, 25, 2, 0x08 / Private /,
We can see that each signal or slot has five plastic representations.

Sound
  • 5. Check the mask.

//Methodflags is an enumeration type. We can see that methodsignal = 0x04 and methodslot = 0x08;

// slots: name, argc, parameters, tag, flags
3, 0, 25, 2, 0x08 / Private /,

  • 6. Judge the link type. The default is QT:: autoconnection.
Emit

We introduce some connection types:

  • 1. Autoconnection: automatic connection: by default, the thread and bad object sent by the signal are equivalent to directconnection in one thread, and queuedconnection in different threads.
  • 2. Directconnection: direct connection: it is equivalent to calling the slot function directly. However, when the signaled thread and the slot object are no longer the same thread, the slot function is executed in the issued signal.
  • 3. Queuedconnection: queue connection: implemented internally through postevent. It is not called in real time, and the slot function is always executed in the thread where the slot function object is located. If the signal parameter is a reference type, a separate copy is made. Thread safe.
  • 4. Blockingqueuedconnection: blocking connection: this connection method can only be used for the signaled thread and the object of the slot function. It can be used in a thread any more. It is implemented by semaphore + postevent, and is not called in real time. The slot function is always in the slot The function object is executed in the thread where the function object is located. However, the current thread will be blocked after the execution of the slot function is completed.
  • 5. Uniqueconnection: prevents duplicate connections. If the current signal and slot are already connected, they are no longer connected.

Finally, it’s where the signal and slot are related to the core:

First, we need to understand the following data structures:

The above three data structures are very important. QObject is our most familiar base class, and qobjectprivate is its private class for specific implementation. Qobjectprivate inherits from qobjectdata and is accessed by P pointer and D pointer in the form of composition in QObject. In the process of signal and slot correlation, the data structure connection is a very important data structure. The following structure is a vector of the connectionlist:

With the above data structure, we can analyze the following link process. We can see that the following is the connection of the called qmetaobjectprivate, and then the pointer wrapping with qmetaobject:: Connection:


QObjectPrivate:: get (s) method is actually getting a QObjectPrivate instance in QObjec, then calling addConnection method to add to the linked list:

The structure is as follows:

analysis:

  • 1. Each QObject object has a QObject connectionlistvector structure, which is a vector container. The basic units in it are data of the connectionlist type. The number of connectionlists is the same as the number of signals of the QObject object. Each connectionlist corresponds to a signal, which records all connections connected to the signal. We have seen that there are two important members in the definition of connectionlist: first and last. They are both pointers of connection type, pointing to the first and last connection connected to this signal respectively. All connections connected to this signal are organized in a one-way linked list. The nextconnectionlist member in the connection structure is used to point to the next connection in the list.
  • 2. At the same time, each QObject object also has a senders member. Senders is a pointer of connection type. Senders itself is the head node of a linked list. All nodes in the list are connected to a slot on the QObject object. However, the list mentioned in the following paragraph is not the same, although they may have some common nodes.
  • 3. Each connection object is in two linked lists at the same time. One is a one-way linked list organized by nextconnectionlist members of connection. The common point of each node in this single list is that they all rely on the same signal of the same QObject object. The head node of this list is the first in the connectionlist structure corresponding to the signal; the other is organized by the next and prev members of connection Bidirectional linked list. The common feature of each node in this bi-directional linked list is that their slots are on the same QObject object, and the head node of the list is the sender of the QObject object. The two linked lists will have cross (common nodes), but they have different link pointers, so they are not the same list.
  • 4. In connect, a new connection object is first created. After setting the connection information, it is added to the two linked lists mentioned above. When disconnecting, it is removed from the two linked lists and then deleted. When a QObject object is destroyed, all connections in the bidirectional linked list pointed to by its sender pointer will be removed one by one!

Step 3: send signal to receive signal

  • 1, we click on the button above and then call it into the onDestory slot, which is where we write the signal trigger:
  • 2. The next step is the MOC_ MainWindow.cpp The code inside calls the static method activate of qmetaobject

//Then go to the real qmetaobject:: activate

Our example is autocontion mode, so the following code will be executed for callback:

We finally see that the function calls back to the MOC_ MainWindow.cpp Inside, then call the corresponding slot onClean;

Finally, after calling here, print out: “MainWindow:: onclean”

Finally, after the call is finished, it will return to ondestory

Note: if we do the M_ Release operation of testwidget object (delete M_ Testwidget), and then to emit clean() in ondestory(); after accessing members, you must crash, so pay attention.

1、https://woboq.com/blog/how-qt…

2. Qt5.7 source code

3. The signal and slot demo implemented in C + + http://note.youdao.com/notesh…

Home All Classes Main Classes Annotated Grouped Classes Functions

Signals and slots are used for communication between objects. Thesignal/slot mechanism is a central feature of Qt and probably thepart that differs most from other toolkits.

In GUI programming we often want a change in one widget to be notifiedto another widget. More generally, we want objects of any kind to beable to communicate with one another. For example if we were parsingan XML file we might want to notify a list view that we're using torepresent the XML file's structure whenever we encounter a new tag.

Qt Signals Slots Emit

Older toolkits achieve this kind of communication using callbacks. Acallback is a pointer to a function, so if you want a processingfunction to notify you about some event you pass a pointer to anotherfunction (the callback) to the processing function. The processingfunction then calls the callback when appropriate. Callbacks have twofundamental flaws. Firstly they are not type safe. We can never becertain that the processing function will call the callback with thecorrect arguments. Secondly the callback is strongly coupled to theprocessing function since the processing function must know whichcallback to call.

An abstract view of some signals and slots connections

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

The signals and slots mechanism is type safe: the signature of asignal must match the signature of the receiving slot. (In fact a slotmay have a shorter signature than the signal it receives because itcan ignore extra arguments.) Since the signatures are compatible, thecompiler can help us detect type mismatches. Signals and slots areloosely coupled: a class which emits a signal neither knows nor careswhich slots receive the signal. Qt's signals and slots mechanismensures that if you connect a signal to a slot, the slot will becalled with the signal's parameters at the right time. Signals andslots can take any number of arguments of any type. They arecompletely typesafe: no more callback core dumps!

All classes that inherit from QObject or one of its subclasses(e.g. QWidget) can contain signals and slots. Signals are emitted byobjects when they change their state in a way that may be interestingto the outside world. This is all the object does to communicate. Itdoes not know or care whether anything is receiving the signals itemits. This is true information encapsulation, and ensures that theobject can be used as a software component.

An example of signals and slots connections

Slots can be used for receiving signals, but they are also normalmember functions. Just as an object does not know if anything receivesits signals, a slot does not know if it has any signals connected toit. This ensures that truly independent components can be created withQt.

Qt Signal Slot Emit Example

You can connect as many signals as you want to a single slot, and asignal can be connected to as many slots as you desire. It is evenpossible to connect a signal directly to another signal. (This willemit the second signal immediately whenever the first is emitted.)

Together, signals and slots make up a powerful component programmingmechanism.

A Small Example

A minimal C++ class declaration might read:

A small Qt class might read:

This class has the same internal state, and public methods to access thestate, but in addition it has support for component programming usingsignals and slots: this class can tell the outside world that its statehas changed by emitting a signal, valueChanged(), and it hasa slot which other objects can send signals to.

All classes that contain signals or slots must mention Q_OBJECT intheir declaration.

Slots are implemented by the application programmer.Here is a possible implementation of Foo::setValue():

The line emit valueChanged(v) emits the signalvalueChanged from the object. As you can see, you emit asignal by using emit signal(arguments).

Here is one way to connect two of these objects together:

Calling a.setValue(79) will make a emit a valueChanged()signal, which b will receive in its setValue() slot,i.e. b.setValue(79) is called. b will then, in turn,emit the same valueChanged() signal, but since no slot has beenconnected to b's valueChanged() signal, nothing happens (thesignal is ignored).

Note that the setValue() function sets the value and emitsthe signal only if v != val. This prevents infinite loopingin the case of cyclic connections (e.g. if b.valueChanged()were connected to a.setValue()).

A signal is emitted for every connection you make, so if youduplicate a connection, two signals will be emitted. You can alwaysbreak a connection using QObject::disconnect().

Qt Signals Slots Emit In The Dark

This example illustrates that objects can work together without knowingabout each other, as long as there is someone around to set up aconnection between them initially.

The preprocessor changes or removes the signals, slots andemit keywords so that the compiler is presented with standard C++.

Run the moc on class definitions that containsignals or slots. This produces a C++ source file which should be compiledand linked with the other object files for the application. If you useqmake, the makefile rules toautomatically invoke the moc will be added toyour makefile for you.

Signals

Signals are emitted by an object when its internal state has changedin some way that might be interesting to the object's client or owner.Only the class that defines a signal and its subclasses can emit thesignal.

A list box, for example, emits both clicked() andcurrentChanged() signals. Most objects will probably only beinterested in currentChanged() which gives the current list itemwhether the user clicked it or used the arrow keys to move to it. Butsome objects may only want to know which item was clicked. If thesignal is interesting to two different objects you just connect thesignal to slots in both objects.

When a signal is emitted, the slots connected to it are executedimmediately, just like a normal function call. The signal/slotmechanism is totally independent of any GUI event loop. Theemit will return when all slots have returned.

If several slots are connected to one signal, the slots will beexecuted one after the other, in an arbitrary order, when the signalis emitted.

Signals are automatically generated by the mocand must not be implemented in the .cpp file. They can never havereturn types (i.e. use void).

A note about arguments. Our experience shows that signals and slotsare more reusable if they do not use special types. If QScrollBar::valueChanged() were to use a special type such as thehypothetical QRangeControl::Range, it could only be connected toslots designed specifically for QRangeControl. Something as simple asthe program in Tutorial #1 part 5would be impossible.

Slots

Qt Signals Slots Emit

A slot is called when a signal connected to it is emitted. Slots arenormal C++ functions and can be called normally; their only specialfeature is that signals can be connected to them. A slot's argumentscannot have default values, and, like signals, it is rarely wise touse your own custom types for slot arguments.

Since slots are normal member functions with just a little extraspice, they have access rights like ordinary member functions. Aslot's access right determines who can connect to it:

A public slots section contains slots that anyone can connectsignals to. This is very useful for component programming: you createobjects that know nothing about each other, connect their signals andslots so that information is passed correctly, and, like a modelrailway, turn it on and leave it running.

A protected slots section contains slots that this class and itssubclasses may connect signals to. This is intended for slots that arepart of the class's implementation rather than its interface to therest of the world.

A private slots section contains slots that only the class itselfmay connect signals to. This is intended for very tightly connectedclasses, where even subclasses aren't trusted to get the connectionsright.

You can also define slots to be virtual, which we have found quiteuseful in practice.

The signals and slots mechanism is efficient, but not quite as fast as'real' callbacks. Signals and slots are slightly slower because of theincreased flexibility they provide, although the difference for realapplications is insignificant. In general, emitting a signal that isconnected to some slots, is approximately ten times slower thancalling the receivers directly, with non-virtual function calls. Thisis the overhead required to locate the connection object, to safelyiterate over all connections (i.e. checking that subsequent receivershave not been destroyed during the emission) and to marshall anyparameters in a generic fashion. While ten non-virtual function callsmay 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 avery small proportion of the complete function call costs. The same istrue whenever you do a system call in a slot; or indirectly call morethan ten functions. On an i586-500, you can emit around 2,000,000signals per second connected to one receiver, or around 1,200,000 persecond connected to two receivers. The simplicity and flexibility ofthe signals and slots mechanism is well worth the overhead, which yourusers won't even notice.

Meta Object Information

The meta object compiler (moc) parses the classdeclaration in a C++ file and generates C++ code that initializes themeta object. The meta object contains the names of all the signal andslot members, as well as pointers to these functions. (For moreinformation on Qt's Meta Object System, see Whydoesn't Qt use templates for signals and slots?.)

The meta object contains additional information such as the object's class name. You can also check if an objectinherits a specific class, for example:

A Real Example

Here is a simple commented example (code fragments from qlcdnumber.h ).

QLCDNumber inherits QObject, which has most of the signal/slotknowledge, via QFrame and QWidget, and #include's the relevantdeclarations.

Q_OBJECT is expanded by the preprocessor to declare several memberfunctions that are implemented by the moc; if you get compiler errorsalong the lines of 'virtual function QButton::className not defined'you have probably forgotten to run the moc or toinclude the moc output in the link command.

It's not obviously relevant to the moc, but if you inherit QWidget youalmost certainly want to have the parent and namearguments in your constructors, and pass them to the parentconstructor.

Some destructors and member functions are omitted here; the mocignores member functions.

QLCDNumber emits a signal when it is asked to show an impossiblevalue.

If you don't care about overflow, or you know that overflow cannotoccur, you can ignore the overflow() signal, i.e. don't connect it toany slot.

If, on the other hand, you want to call two different error functionswhen the number overflows, simply connect the signal to two differentslots. Qt will call both (in arbitrary order).

A slot is a receiving function, used to get information about statechanges in other widgets. QLCDNumber uses it, as the code aboveindicates, to set the displayed number. Since display() is partof the class's interface with the rest of the program, the slot ispublic.

Several of the example programs connect the newValue() signal of aQScrollBar to the display() slot, so the LCD number continuously showsthe value of the scroll bar.

Note that display() is overloaded; Qt will select the appropriate versionwhen you connect a signal to the slot. With callbacks, you'd have to findfive different names and keep track of the types yourself.

Some irrelevant member functions have been omitted from thisexample.