Signal and slots)

Source: Internet
Author: User
Tags emit readfile

Signal and slots)

The signal and the signal slot are used for communication between objects. The signal and slot mechanisms are important features of QT and may be the most different parts of QT and other frameworks.

Preface

In GUI programming, we usually want to inform another widget that is interested in this change when a widget is changed. In general, we hope that any class of objects can communicate with other objects. For example, if you click a close button, you may want the close () function of the window to be called.

In earlier versions, the toolkit used callback to implement communication between objects mentioned above. Callback refers to a function pointer. Therefore, if you want a processing function to notify you of some things, you can pass another function (callback function) pointer to the processing function. This handler will call the callback function when appropriate. Callback has two important defects: first, they are not type-safe. We cannot determine whether the handler calls the callback function with the correct parameter. Second, the callback is closely related to the handler so that the handler must know which callback to call.

Messages and slots

In QT, we use an alternative callback technology: Signal and slot mechanism. When a special event is generated, a signal is sent. Qt's widgets have many predefined signals. We can also add their own signals to the Child classes of the widgets by inheritance. A slot is a function that can be called to process specific signals. Qt's widgets have many predefined slots, but the common practice is to add their own signals to the Child widgets so that they can manipulate their own signals.

The signal and slot mechanism are secure: the signature of a signal must match the signature of the signal receiving slot. (In fact, the signature in a slot can be less than the one in which the signal is acceptable, because it can ignore some signatures ). Therefore, the signature is consistent, and the compiler can help us detect type matching. Signal and slot are loosely coupled: A class does not know or care which slot accepts the signal it sends. Qt's signal and slot mechanism ensure that they are in the correct connection, and the slot will be called using signal parameters at the right time. Signal and slot can use any number or type of parameters. They are completely type-safe.

All classes that inherit from qobject or their sub-classes (such as qwidget) can contain signals and slots. When objects change their own States, signals are sent. In a sense, they may be interested in the outside world. This is what all objects do during communication. It does not know or care whether there is anything else to accept the signal it sends. This is the real message encapsulation and ensures that the object can be used as a software component.

The slot is used to receive signals, but they are also normal member functions. Just as an object does not know whether something accepts its signal, a slot does not know whether it is connected by a signal. This ensures that QT can create truly independent components.

You can connect any signal to the signal slot you want to connect, and connect one signal to multiple slots as needed. It is also possible to connect the signal directly to another signal (so that the second signal will be sent immediately after the first signal is sent at any time ).

In general, signals and slots constitute a powerful component programming mechanism.

Simple Example

A very small C ++ class declaration is as follows:

Class counter
{
Public:
Counter () {m_value = 0 ;}

Int value () const {return m_value ;}
Void setvalue (INT value );
PRIVATE:
Int m_value;
};

The declaration of a small qobject subclass is:

# Include <qobject>

Class counter: Public qobject
{
Q_object

Public:
Counter () {m_value = 0 ;}

Int value () const {return m_value ;}

Public slots:
Void setvalue (INT value );
Signals:
Void valuechanged (INT newvalue );

PRIVATE:
Int m_value;
};

The qobject class has the same domain as the previous C ++ class and provides public functions to accept this domain. However, it also adds the signal and slots (signals-slots) support for component programming. This class can send a signal via valuechanged () to tell the external world that his domain has changed, and it has a slot that can receive signals from other objects.

All classes that contain signals and slots must mention q_object at the beginning of their declaration. And they must inherit (directly or indirectly) qobject.

It can be implemented by the application writer. Here is a possible implementation of counter: setvaule:

Void counter: setvalue (INT value)
{
If (value! = M_value)
{
M_value = value;
Emit valuechanged (value );
}
}

This line of emit sends a valuechanged signal from the object and uses the new value as the parameter.

In the following code snippet, we create two counter objects and use the qobject: connect () function to connect the valuechanged () signal of the first object to the setvalue () slot of the second object.

Counter A, B;
Qobject: connect (& A, signal (valuechanged (INT )),
& B, slot (setvalue (INT )));
A. setvalue (12); // A. Value () = 12, B. Value () = 12
B. setvalue (48); // A. Value () = 12, B. Value () = 48

The call of function A. setvalue (12) causes the valuechange (12) signal to be sent. The setvalue () slot of object B accepts this signal, that is, the setvalue () function is called. Then B sends the valuechange () signal, but the signal is ignored because there is no slot to connect B to the valuechange () signal.

Note that only when value! = M_value, The setvalue () function sets a new value and sends a signal. This avoids endless loops in the case of loop connections (such as B. valuechanged () and A. setvalue.

The signal will be sent to any slot that you have established a connection; if the connection is repeated, two signals will be sent. You can always use the qobject: disconnect () function to disconnect a connection.

This example shows that objects can work collaboratively without knowing any information about each other. To achieve this goal, you only need to connect the object through the call of the function qobject: connect () or use the features of UIC automatic connections.

Compile this example

The C ++ pre-compiler will change or remove the keywords signals, slots, and emit, so that the standard C ++ compiler can be used.

Run MOC on a class with defined signals and slots. This will generate a C ++ source file that can be compiled and connected to other object files into an application. If you use the qmake tool, the MOC rules will be automatically called in your MAKEFILE file.

Signal

When the internal state of an object changes, the signal is sent. In some ways, it may be interesting for the object proxy or owner. Only the object or sub-object that defines the signal can transmit the signal.

When a signal is sent, the connected slot usually runs immediately, just like executing a common function call. When this happens, the signal and slot mechanisms are completely independent of any GUI event loop. The slot will return after the code defined in the emit domain is executed. When queued connections is used, the code after the keyword emit continues to be executed.

If several slots are connected to a signal, when the signal is sent, the slot is executed one by one in any order.

Note about parameters: our experience shows that if the signal and slot do not use special types, they will become more reusable. If qscrollbar: valuechanged () uses a special type, such as hypothetical qrangecontrol: range, it can only be connected to a slot designed to process qrangecontrol. There is no simple example like tutorial 5.

Slot

When a signal is sent, the slot connected to it is called. A slot is a common C ++ function and called in the normal way. It is only characteristic that it can be connected by signals.

Since the slot is just a common member function, it follows the C ++ rules directly when called. However, for slots, they can be called by any component through a signal-slot connection regardless of their access permissions. That is to say, the signal sent from an instance of any class can cause the private slot of an instance of another class not related to this class to be called.

You can also define a virtual slot, which is also very useful in practice.

Due to the increased flexibility, the signal and slot are a little slower than the callback, although this can be ignored for real applications. Generally, sending a signal connecting to a slot is 10 times slower than directly calling the receiver that is not a virtual call. This is the overhead required to locate the connection object. You can safely repeat all the connections (for example, check whether the concurrent receiver is damaged during the launch) and arrange any parameters in the general way. When ten non-virtual function calls sound great, they actually have less overhead than any new or delete operations. For example, when you perform a string, vector, or list operation, new and delete are required, while the overhead of signals and slots is only a small part of the total function call cost.

No matter when you use a slot for a system call or indirect call, more than 10 function times are the same. On a i586-500 machine, you can send more than 2,000,000 signals per second to one receiver, or send 1,200,000 signals per second to two recipients. Compared with the simplicity and flexibility of the signal and slot mechanisms, his time overhead is completely worthwhile, and your users cannot even notice it.

NOTE: If other libraries define variables as signals and slots, the compiler may encounter errors or warnings when connecting to QT-based applications. To solve this problem, use the # UNDEF preprocessing symbol.

Metadata

The metadatabase Compiler (MOC) parses the class declaration in a C ++ file and generates the C ++ code for initializing the metadatabase. Meta objects include the names of signals and slots, and pointers to these functions.

If (widget-> inherits ("qiniactbutton ")){
Qiniactbutton * button = static_cast <qiniactbutton *> (widget );
Button-> toggle ();
}

The usage of metadata can also be qobject_cast <t> (), which is similar to qobject: inherits (), but is less prone to errors.

If (qiniactbutton * button = qobject_cast <qiniactbutton *> (widget ))
Button-> toggle ();

View the meta-Object System for more information.

One instance

This is a simple example that has been commented out (the code snippet is selected from qlcdnumber. h ).

# Ifndef lcdnumber_h
# Define lcdnumber_h

# Include <qframe>

Class lcdnumber: Public qframe
{
Q_object

Lcdnumber inherits to qobject through qframe and qwiet. It contains most of signal-slot knowledge. This is a bit similar to the built-in qlcdnumber component.

The q_object macro is expanded by a pre-processor to declare the machine member functions implemented by MOC. If your compiler has the following error: "undefined reference to vtable for lcdnumber ", you may have forgotten to run MOC or have not used the connection command to include the MOC output.

Public:
Lcdnumber (qwidget * parent = 0 );

Lcdnumber is not obviously related to MOC, But if you inherit qwidege, you can almost certainly have a parent object variable in your constructor, and want to pass it to the constructor of the base class.

Destructor and some member functions are omitted here; MOC ignores member functions.

Signals:
Void overflow ();

When lcdnumbe is required to display an impossible value, a signal is sent.

If you do not pay attention to overflow, or you know That overflow does not occur, you can ignore the overflow () signal, for example, not connecting it to any slot.

If, on the other hand, you want to call two different error handler functions when there is a number overflow, you can simply connect this signal to two different slots. Qt will call two functions (unordered ).

Public slots:
Void display (INT num );
Void display (double num );
Void display (const qstring & Str );
Void sethexmode ();
Void setdecmode ();
Void setoctmode ();
Void setbinmode ();
Void setsmalldecimalpoint (bool point );
};

# Endif

A slot is an acceptance function used to obtain information changes of other widgets. The lcdnumber is used to set the displayed number, just like the code above. Because display () is an interface for this class and other parts of the program, this slot is public.

Several routines connect the valuechanged () signal of the qscrollbar to the display () slot, so the LCD number can continue to display the value of the scroll bar.

Note that display () is overloaded. When a signal is connected to a slot, QT selects the most suitable one. For callback, you will find five different names and track the types by yourself.

An unrelated member function is ignored in this example.

Use of advanced signals and slots

When you need the information of the signal sender, QT provides a function qobject: sender (), which returns a pointer to a signal sending object.

When several signals are connected to the same slot and the slot needs to process different signals, the qsignalmapper class can be used.

Suppose you use three buttons to determine which file to open: tax file "," accounts file ", or" report file ".

To open genuine files, you need to separately connect their signal qpushbutton: clicked () to readfile (). Then, setmapping () of qsignalmapper is used to map all clicked () signals to a qsignalmapper object.

Signalmapper = new qsignalmapper (this );
Signalmapper-> setmapping (taxfilebutton, qstring ("taxfile.txt "));
Signalmapper-> setmapping (accountfilebutton, qstring ("accountsfile.txt "));
Signalmapper-> setmapping (reportfilebutton, qstring ("reportfile.txt "));

Connect (taxfilebutton, signal (clicked ()),
Signalmapper, slot (MAP ()));
Connect (accountfilebutton, signal (clicked ()),
Signalmapper, slot (MAP ()));
Connect (reportfilebutton, signal (clicked ()),
Signalmapper, slot (MAP ()));

Then, connect the mapped () signal to readfile () and open different files according to the pressed button.

Connect (signalmapper, signal (mapped (const qstring &)),
This, slot (readfile (const qstring &)));

Use third-party signals slots in QT

It is possible to use third-party signals slots in QT. You can even use two mechanisms in the same category. You only need to add the following statement to your qmake project file (. Pro:

Config + = no_keywords

It tells QT not to define the MOC keywords signals, slots, and emit, because these names may be used in third-party libraries, such as boost. You can simply replace them with q_signals, q_slots, and q_emit with QT macros to continue using signals and slots.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.