Signal and slot mechanism of Qt

xiaoxiao2021-03-05  30

Contents: I. Introduction II signal three or four association, signals and slots slots V. Meta Object Facility six or seven sample program, resources should pay attention to the issue of introduction Author: Tang Xinhua (xhsmart@263.net) Software Engineer Signal and Slot As the core mechanism of QT in QT programming, this paper introduces some basic concepts, meta-object tools, and some issues that should be noted during the actual use process. QT is a cross-platform C GUI application architecture, which provides a rich window component set, object-oriented, easy to expand, real component programming, etc., more striking is the most popular KDE desktop environment on Linux It is based on the QT library. Qt supports the following platforms: MS / Windows-95, 98, NT and 2000; UNIX / X11-Linux, Sun Solaris, HP-UX, Digital UNIX, IBM AIX, SGI IRIX; Embeddd-supports FrameBuffer Linux platform. With the rapid development and popularity of KDE, QT is likely to be a GUI preferences when software development on the Linux window platform. First, the overview signal and the groove mechanism are the core mechanism of QT, and the QT programming must be understood by the signal and the slot. Signals and slots are advanced interfaces, which are used to communicate between objects, which is the core characteristics of QT, and is also an important part of the Qt difference between other toolkits. Signals and slots are a communication mechanism defined by QT, which is independent of the standard C / C language, so the correct processing signals and slots must be used, which must be used as a Qt tool called MOC (Meta Object Compiler). A C preprocessor, which automatically generates the required additional code for high-level event processing. In the multi-GUI toolkit we are well known, the widget has a callback function to respond to each action that they can trigger, which is usually a pointer to a function. However, the signals and slots in the QT are replaced, so that we have written these communication programs more concise. Signals and slots can carry any quantity and any type of parameters, they are fully secure, which will not generate Core Dumps like the backup function. All classes derived from QObject or their subclasses (eg Qwidget) can include signals and slots. When the object changes its state, the signal is transmitted by the object (EMIT), which is all the things to do, it does not know who is receiving this signal. This is the real information package, which ensures that the object is used as a real software component. The slot is used to receive signals, but they are ordinary object member functions. A slot does not know if any signal is connected to yourself. Moreover, the object does not understand the specific communication mechanism. You can connect a lot of signals with a single slot, or connect a single signal to a lot of slots, even if a signal is connected to another signal, then when the first signal is transmitted The system will immediately transmit the second signal. In summary, the signal and slot construct a powerful component programming mechanism. Second, the signal changes the internal state of its client or owner, and the signal is transmitted by an object. Only the class defined by this signal and its derived class can transmit this signal. When a signal is transmitted, the groove associated therewith will be executed immediately, just like a normal function call. The signal-groove mechanism is completely independent of any GUI event cycle. Only when all the slots returns later, the transmit function (EMIT) is returned. If there is a plurality of slots associated with a signal, then the slots will be executed one by one, but the order they perform will be random, uncertain, we can't be artificially Specify which one is executed, which one is executed.

The statement of the signal is conducted in the header file, the QT's Signals keyword indicates that the signal declaration area is entered, and then the signal can be declared. For example, three signals are defined below: signals: void mysignal (); void mysignal (int x); void mysignalparam (int x, int y); in the above definition, signals is the keyword of QT, not C / C . The next line Void mysignal () defines the signal mysignal. This signal does not carry parameters; the next line Void MySignal (int X) defines the rename signal MySignal, but it carries a shaped parameter, which is a bit similar to C . Musical function. The declaration of the signal from the form is the same as the ordinary C function, but the signal has no functional body definition. In addition, the return type of the signal is Void, do not expect any useful information that can be returned from the signal. The signal is automatically generated by MOC, which should not be implemented in the .cpp file. Third, the groove groove is a normal C member function, which can be adjusted normally, and their unique specialty is that many signals can be associated with them. This slot will be called when the signal associated with it is transmitted. The groove can have parameters, but the parameters of the grooves cannot have a default. Since the slot is a normal member function, the same is true to other functions, and they have access to access. The access rights of the groove determine who can be associated with it. Like ordinary C member functions, the groove function is divided into three types, namely public slots, private slots, and protected slots. Public Slots: The slot declared in this area means that any object can be connected to it. This is very useful for component programming, you can create objects that don't know each other, connect their signals to the slot to allow information to be passed correctly. Protected Slots: The slot declared in this area means that the current class and its subclasses can connect the signal to it. This applies to those grooves, which are part of the implementation, but their interface interface is facing exterior. Private slots: The slot declared in this area means that only classes can connect signals with them. This applies to a very close class. The slot can also be declared as a virtual function, which is also very useful. The declaration of the slot is also carried out in the header file. For example, the three slots: public slots: void (); void myslot (int x); void mysignalparam (int x, int y); four, the association of the signal and the groove will be used by calling the Qobject object A signal of an object is associated with the groove function of another object, so when the transmitter transmits the signal, the receiver's groove function will be called. The function is defined as follows: BOOL Qobject :: Connect (const QObject * sender, const char * signal, const char *) [static] This function is to use the signal Signal in the transmitter Sender object with The member slot function in the recipient Receiver is linked. The macro Signal () must be used when specifying the signal SIGNAL, and the macro slot () must be used when specifying the groove function. If the transmitter is the same object with the recipient, the recipient parameter can be omitted in the Connect call.

For example, two objects are defined below: Label object label and scroll bar object Scroll, and associate the valueChanged () signal with the setNum () of the tag object, and the other signal also carries a shaped parameter, so that the tag always displays the scroll bar The value of the location. Qlabel * label = new qlabel; qscrollbar * scroll = new qscrollbar; Qobject :: Connect (Scroll, Signal (ValueChanged (int)), label, slot (setNum (int))); one signal can even be associated with another signal Look at the example below: Class MyWidget: Public Qwidget: Public Qwidget {public: mywidget (); ... sign: void asignal (); ... private: ... qpushbutton * Abutton;}; mywidget :: myWidget () {Abutton = New QPushbutton (this); connection (here)), Signal ()));} In the above constructor, MyWidget created a private button Abutton, click the click event generated by the button. The signal Clicked () is associated with another signal asignal (). In this way, when the signal Clicked () is transmitted, the signal asignal () is also transmitted. Of course, you can also directly associate with a private groove function, then transmit an ASIGNAL () signal in the slot, which seems to be a bit redundant. When the signal is not necessary to remain associated with the slot, we can use the disconnect function to disconnect. It is defined as follows: BOOL QOBJECT :: Disconnect (const QObject * sender, const char * signal, const object * receiver, const char * member) [static] This function is disconnected from the signal and the groove function in the recipient. Inter-association. There are three situations that must be used with disconnect () functions: Disconnect any object associated with an object. This seems to be a bit unbelievable, in fact, when we define one or more signals in an object, these signals are associated with the slots in the other object, and if we have to cut off these associations, you can use this method. Very simple. Disconnect (MyObject, 0, 0, 0) or myObject-> disconnect () is disconnected from any association with a particular signal. Disconnect (MyObject, Signal (MySignal ()), 0, 0), or myObject-> disconnect (Signal (mysignal ()) is disconnected between the two objects. Disconnect (MyObject, 0, MyRecEiver, 0) or MyObject-> Disconnect (MyReceiver) can be used as a wildcard in the disconnect function, indicating any signal, any receiving object, any groove function in the receiving object. However, the transmitter Sender cannot be 0, and the values ​​of the other three parameters can be equal to 0. V. Element Object Compiler Compiler MOC (Meta Object Compiler) analyzes the class declaration in the C file and generates C code for initialization dollar objects, and the element object contains all the signals and slots and pointers to these functions. .

MOC reads the C source file, if you find a class with a Q_Object macro declaration, it generates another C source file, which contains the meta-object code of the class. For example, suppose we have a header file mysignal.h, including a signal or slot in this file, then the MOC tool will automatically generate a C source file called mysignal.moc.h according to the file before compiling. Submit it to the compiler; Similarly, corresponding to the mysignal.cpp file MOC tool will automatically generate a submitted to the compiler with the mysignal.moc.cpp file. The meta-object code is required by the Signal / Slot mechanism. The C source file generated by MOC must compile and connect with the class implementation, or use a #include statement to include it into the source file of the class. The MOC does not expand the #include or #define macro definition, it is just a simple skip that any pre-processing instructions encountered. Sixth, the program sample is given here a simple sample program, and three signals, three slots functions are defined in the program, and then the signal is associated with the slot, each groove function is just a simple pop-up window window. . The reader can generate a simple QT application with KDevelop and then add the following code to the corresponding program. The declaration of the signal and groove function is generally located in the header file, and the Q_Object statement must be counted in the start position of the class declaration, which is indispensable, it will tell the compiler to apply the MOC tool before compiling. Keyword Signals indicates the statement of subsequent signals. Signals uses multiple forms instead of singing, and Siganls does not have PUBLIC, PRIVATE, PROTECTED, etc. This is different from Slots. In addition, Signals, Slots Keywords are QT you defined, not a keyword in C . The statement of the signal is similar to the declaration of the function and the declaration of the variable, the left side must have a type, the right side to have parentheses, if you want to pass the parameters in the slot, specify the type of each form parameter in parentheses, of course, the formal parameters The number can be more than one. Keyword Slots indicates the declaration of the Subsequent start slot, where Slots uses the plural form. Like a statement of a normal function, the declaration of the slot can carry zero or multiple form parameters. Since the statement of the signal is similar to the declaration of the ordinary C function, the signal can also be declared in the form of a defraud in C , which is the same name but the parameters are different. For example, the first defined void mysignal () does not have a parameter, while the second definition has parameters, from here we can see the signal mechanism of Qt is very flexible. The connection between the signal and the groove must be specified in advance using the Connect function. If you want to disconnect the connection between the two, you can use the function disconnect.

//tsignal.h ... class tsignalapp: public qMainWindow {q_object ... // signal declaration area sign: // declared signal mysignal () void mysignal (); // declared signal mysignal (int) Void MySignal (int X) ); // Declaration signal mysignalparam (int, int, int) void mysignalparam (int x, int y); // Slot declaration area public slots: // declared slot function myslot () void myslot (); // declared slot function myslot INT) Void MySlot (INT X); // Declaration Slot Function MySignalParam (int, int) Void MySignalParam (int x, int y);} ... //tsignal.cpp ... Tsignalapp :: tsignalapp () {. .. // Associate the signal MySignal () associated with the slot myslot (), slot (myslot ())); // Block the signal MySignal (int) associated with the slot myslot (int)) Connect (This, Signal (INT)), Slot (MySlot (int))); // Associates the signal MySignalParam (int, int, int, int, int, int, int, int, ") Connect (THISIGNALPAR (MysignalParam) INT, INT), Slot (MySlotParam (int, int))));} // Define slot function myslot () void Tsignalapp :: myslot () qmessagebox :: About (this, "tsignal", "this is a signal / slot sample parameter. ");} // Define the slot function myslot (int) void tsignalapp :: myslot (int x) {QMESSAGEBOX :: About (this," tsignal "," this is a signal / slot sample with one Parameter. " );} // Define slot function myslotparam (int, int) void Tsignalapp :: myslotparam (int x, int y) {char s [256]; Sprintf (s, "x:% dy:% d", x, y ); QMessagebox :: About (this, "tsignal", s);} void Tsignalapp :: slotfilenew () {// transmit signal mysignal () Emit mysignal (); // Transmit signal MySignal (int) Emit MySignal (5) ; // Transmit signal MySignalParam (5,100) Emit MySignalParam (5,100);} Seven Some are targeted to avoid some errors. Here will be described in this regard. 1. The signal and the trough is very high, but the true callback function is compared, since the flexibility is added, there is still a loss at the speed, of course, this loss is relatively small, passed in one The I586-133 machine test is 10 microseconds (running Linux), which shows the simplicity provided by this mechanism, flexibility is still worth it. But if we want to pursue high efficiency, such as such mechanisms should be used as much as possible in real-time systems.

2. The signal and groove mechanism are the same as the normal function. If not improper use, it is also possible to generate a dead cycle when executed. Therefore, it is necessary to pay attention to avoid indirect forming infinite loops when defining the groove function, that is, the received same signal is transmitted again in the slot. For example, in the example, if the statement Emit MySignal () can be formed in the myslot () groove function, it can form a dead cycle. 3. If a signal is associated with a plurality of slots, then when this signal is transmitted, the order associated with the associated groove will be random. 4. Macro definition cannot be used in the parameters of Signal and Slot. Since the MOC tool does not expand #define, the macros carrying parameters in Signals and Slots cannot work correctly if they do not have parameters. For example, in the following example, the parameters of the macro Signedness (a) as the signal are informal: #ifdef ultrix #define Signedness (a) unsigned a #else #define signedness (a) a #ENDIF Class Whatver: Public Qobject {[...] Signals: Void Somesignal (Signedness (a)); [...]}; 5. Construction function cannot be used in the Signals or Slots declaration area. Indeed, putting a constructor in the Signals or Slots district is not understandable, in any case, you cannot put them in private slots, protected slots, or public Slots districts. The following usage is an inclusion: Class SomeClass: Public Qobject {Q_Object Public Slots: SomeClass (QObject * Parent, const char * name): Qobject (PARENT, NAME) {} // Declaring constructor in the slot declaration area Syntax [...]}; 6. Function pointer cannot be used as a signal or groove parameter. For example, in the following example, the parameters are not syntax in the following example: Class SomeClass: Public QObject {q_object [...] public slots: Void Apply (Void (* ApplyFunction) (VOID (* ApplyFunction) Qlist *, void *), char *); // does not syntax}; you can bypass this limit: typedef void (* ApplyFunctionType) (Qlist *, void *); Class SomeClass: Public Qobject {q / qbject [ ...] Public Slots: Void Apply (ApplyfunctionType, Char *);}; 7. Signal and slots cannot have default parameters. Since Signal-> SLOT binding occurs at runtime, then it is difficult to use the default parameters conceptually. The following usage is unreasonable: Class SomeClass: Public QObject {Q_Object Public Slots: Void Someslot (int x = 100); // Defines the default value of X to 100, using an error in the groove function declaration}; 8. Signal and slots can also carry template class parameters. If the signal, the slot is declared as a template parameter, even if the MOC tool does not report an error, it is impossible to obtain the expected result.

For example, in the following example, the groove function will not be called correctly when the signal is transmitted: [...] public slots: void myWidget :: setLocation (pair location); [...] public signals: void myObject :: Moved (Pair location); however, you can use the typedef statement to bypass this limit. As shown below: Typedef Pair Intpair; [...] public slots: void myWidget :: setLocation (intPair location); [...] public signals: void myObject :: moved (intPair location); In this way, you You can get the correct result. 9. Nested classes cannot be located in the signal or groove area, and there is no signal or groove. For example, in the following example, the declaration groove B () is informative in Class B, and the groove B () in the signal area is also informal. Class A {Q_Object Public: Class B {public slots: // Declared slots in nested classes to not syntax void b (); [....]}; sign: class b {// Declare nested in the signal area The class is inconspicuous void b (); [....]}:}; 10. The friend declaration cannot be located in the signal or slot declaration area. Instead, they should be declared in a PRIVATE, PROTECTED, or PUBLIC zone of ordinary C . The following example is the non-syntax specification: Class SomeClass: Public QObject {q_object [...] sign or // Signal Defining Region Friend Class ClassTemplate; // The definition is not syntax}; related resources Qt KDevelop Author Tang Xinhua Software engineer. Email: xhsmart@263.net is taken from: IBM DeveloperWorks China website

转载请注明原文地址:https://www.9cbs.com/read-34245.html

New Post(0)