diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /doc/src/signalsandslots.qdoc | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'doc/src/signalsandslots.qdoc')
-rw-r--r-- | doc/src/signalsandslots.qdoc | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/doc/src/signalsandslots.qdoc b/doc/src/signalsandslots.qdoc new file mode 100644 index 0000000..5432bd4 --- /dev/null +++ b/doc/src/signalsandslots.qdoc @@ -0,0 +1,418 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page signalsandslots.html + \title Signals and Slots + \ingroup architecture + \brief An overview of Qt's signals and slots inter-object + communication mechanism. + + 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. + + \tableofcontents + + \section1 Introduction + + 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 \gui{Close} button, we probably want the + window's \l{QWidget::close()}{close()} function to be called. + + Older 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. Callbacks have two fundamental flaws: Firstly, they + are not type-safe. We can never be certain that the processing + function will call the callback with the correct arguments. + Secondly, the callback is strongly coupled to the processing + function since the processing function must know which callback + to call. + + \section1 Signals and Slots + + 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. + + \img abstract-connections.png + \omit + \caption An abstract view of some signals and slots connections + \endomit + + 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. + 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. + + 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. + + \section1 A Small Example + + A minimal C++ class declaration might read: + + \snippet doc/src/snippets/signalsandslots/signalsandslots.h 0 + + A small QObject-based class might read: + + \snippet doc/src/snippets/signalsandslots/signalsandslots.h 1 + \codeline + \snippet doc/src/snippets/signalsandslots/signalsandslots.h 2 + \snippet doc/src/snippets/signalsandslots/signalsandslots.h 3 + + The QObject-based version has the same internal state, and provides + public methods to access the state, but in addition it has support + for component programming using signals and slots. This class can + tell the outside world that its state has changed by emitting a + signal, \c{valueChanged()}, and it has a slot which other objects + can send signals to. + + All classes that contain signals or slots must mention + Q_OBJECT at the top of their declaration. They must also derive + (directly or indirectly) from QObject. + + Slots are implemented by the application programmer. + Here is a possible implementation of the \c{Counter::setValue()} + slot: + + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 0 + + The \c{emit} line emits the signal \c valueChanged() from the + object, with the new value as argument. + + In the following code snippet, we create two \c Counter objects + and connect the first object's \c valueChanged() signal to the + second object's \c setValue() slot using QObject::connect(): + + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 1 + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 2 + \codeline + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 3 + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 4 + + Calling \c{a.setValue(12)} makes \c{a} emit a + \c{valueChanged(12)} signal, which \c{b} will receive in its + \c{setValue()} slot, i.e. \c{b.setValue(12)} is called. Then + \c{b} emits the same \c{valueChanged()} signal, but since no slot + has been connected to \c{b}'s \c{valueChanged()} signal, the + signal is ignored. + + Note that the \c{setValue()} function sets the value and emits + the signal only if \c{value != m_value}. This prevents infinite + looping in the case of cyclic connections (e.g., if + \c{b.valueChanged()} were connected to \c{a.setValue()}). + + A signal is emitted for every connection you make; if you + duplicate a connection, two signals will be emitted. You can + always break a connection using QObject::disconnect(). + + This example illustrates that objects can work together without needing to + know any information about each other. To enable this, the objects only + need to be connected together, and this can be achieved with some simple + QObject::connect() function calls, or with \c{uic}'s + \l{Using a Designer .ui File in Your Application#Automatic Connections} + {automatic connections} feature. + + \section1 Building the Example + + The C++ preprocessor changes or removes the \c{signals}, + \c{slots}, and \c{emit} keywords so that the compiler is + presented with standard C++. + + By running the \l moc on class definitions that contain signals + or slots, a C++ source file is produced which should be compiled + and linked with the other object files for the application. If + you use \l qmake, the makefile rules to automatically invoke \c + moc will be added to your project's makefile. + + \section1 Signals + + 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. + Only the class that defines a signal and its subclasses can emit the + signal. + + 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 \c emit + statement will occur once all slots have returned. The situation is + slightly different when using \l{Qt::ConnectionType}{queued + connections}; in such a case, the code following the \c emit keyword + will continue immediately, and the slots will be executed later. + + If several slots are connected to one signal, the slots will be + executed one after the other, in an arbitrary order, when the signal + is emitted. + + Signals are automatically generated by the \l moc and must not be + implemented in the \c .cpp file. They can never have return types + (i.e. use \c 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. + + \section1 Slots + + 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. + + 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 \c + new or \c delete operation, for example. As soon as you perform a + string, vector or list operation that behind the scene requires + \c new or \c 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. On an i586-500, you can + emit around 2,000,000 signals per second connected to one + receiver, or around 1,200,000 per second connected to two + receivers. 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 \c signals + or \c slots may cause compiler warnings and errors when compiled + alongside a Qt-based application. To solve this problem, \c + #undef the offending preprocessor symbol. + + \section1 Meta-Object Information + + The meta-object compiler (\l moc) parses the class declaration in + a C++ file and generates C++ code that initializes the + meta-object. The meta-object contains the names of all the signal + and slot members, as well as pointers to these functions. + + The meta-object contains additional information such as the + object's \link QObject::className() class name\endlink. You can + also check if an object \link QObject::inherits() + inherits\endlink a specific class, for example: + + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 5 + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 6 + + The meta-object information is also used by qobject_cast<T>(), which + is similar to QObject::inherits() but is less error-prone: + + \snippet doc/src/snippets/signalsandslots/signalsandslots.cpp 7 + + See \l{Meta-Object System} for more information. + + \section1 A Real Example + + Here is a simple commented example of a widget. + + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 0 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 1 + \codeline + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 2 + \codeline + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 3 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 4 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 5 + + \c LcdNumber inherits QObject, which has most of the signal-slot + knowledge, via QFrame and QWidget. It is somewhat similar to the + built-in QLCDNumber widget. + + The Q_OBJECT macro is expanded by the preprocessor to declare + several member functions that are implemented by the \c{moc}; if + you get compiler errors along the lines of "undefined reference + to vtable for \c{LcdNumber}", you have probably forgotten to + \l{moc}{run the moc} or to include the moc output in the link + command. + + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 6 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 7 + + It's not obviously relevant to the moc, but if you inherit + QWidget you almost certainly want to have the \c parent argument + in your constructor and pass it to the base class's constructor. + + Some destructors and member functions are omitted here; the \c + moc ignores member functions. + + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 8 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 9 + + \c LcdNumber emits a signal when it is asked to show an impossible + value. + + If you don't care about overflow, or you know that overflow + cannot occur, you can ignore the \c overflow() signal, i.e. don't + connect it to any slot. + + If on the other hand you want to call two different error + functions when the number overflows, simply connect the signal to + two different slots. Qt will call both (in arbitrary order). + + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 10 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 11 + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 12 + \codeline + \snippet doc/src/snippets/signalsandslots/lcdnumber.h 13 + + A slot is a receiving function used to get information about + state changes in other widgets. \c LcdNumber uses it, as the code + above indicates, to set the displayed number. Since \c{display()} + is part of the class's interface with the rest of the program, + the slot is public. + + Several of the example programs connect the + \l{QScrollBar::valueChanged()}{valueChanged()} signal of a + QScrollBar to the \c display() slot, so the LCD number + continuously shows the value of the scroll bar. + + Note that \c display() is overloaded; Qt will select the + appropriate version when you connect a signal to the slot. With + callbacks, you'd have to find five different names and keep track + of the types yourself. + + Some irrelevant member functions have been omitted from this + example. + + \section1 Advanced Signals and Slots Usage + + For cases where you may require information on the sender of the + signal, Qt provides the QObject::sender() function, which returns + a pointer to the object that sent the signal. + + The QSignalMapper class is provided for situations where many + signals are connected to the same slot and the slot needs to + handle each signal differently. + + Suppose you have three push buttons that determine which file you + will open: "Tax File", "Accounts File", or "Report File". + + In order to open the correct file, you use QSignalMapper::setMapping() to + map all the clicked() signals to a QSignalMapper object. Then you connect + the file's QPushButton::clicked() signal to the QSignalMapper::map() slot. + + \snippet doc/src/snippets/signalmapper/filereader.cpp 0 + + Then, you connect the \l{QSignalMapper::}{mapped()} signal to + \c{readFile()} where a different file will be opened, depending on + which push button is pressed. + + \snippet doc/src/snippets/signalmapper/filereader.cpp 1 + + \sa {Meta-Object System}, {Qt's Property System} + + \target 3rd Party Signals and Slots + \section2 Using Qt with 3rd Party Signals and Slots + + It is possible to use Qt with a 3rd party signal/slot mechanism. + You can even use both mechanisms in the same project. Just add the + following line to your qmake project (.pro) file. + + \snippet doc/src/snippets/code/doc_src_containers.qdoc 22 + + It tells Qt not to define the moc keywords \c{signals}, \c{slots}, + and \c{emit}, because these names will be used by a 3rd party + library, e.g. Boost. Then to continue using Qt signals and slots + with the \c{no_keywords} flag, simply replace all uses of the Qt + moc keywords in your sources with the corresponding Qt macros + Q_SIGNALS (or Q_SIGNAL), Q_SLOTS (or Q_SLOT), and Q_EMIT. +*/ |