diff options
Diffstat (limited to 'doc/signalsandslots.doc')
-rw-r--r-- | doc/signalsandslots.doc | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/doc/signalsandslots.doc b/doc/signalsandslots.doc new file mode 100644 index 000000000..3762f337b --- /dev/null +++ b/doc/signalsandslots.doc @@ -0,0 +1,410 @@ +/**************************************************************************** +** +** Explanation of moc and the meta object system +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the Qt GUI Toolkit. +** +** This file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free +** Software Foundation and appearing in the files LICENSE.GPL2 +** and LICENSE.GPL3 included in the packaging of this file. +** Alternatively you may (at your option) use any later version +** of the GNU General Public License if such license has been +** publicly approved by Trolltech ASA (or its successors, if any) +** and the KDE Free Qt Foundation. +** +** Please review the following information to ensure GNU General +** Public Licensing retquirements will be met: +** http://trolltech.com/products/qt/licenses/licensing/opensource/. +** If you are unsure which license is appropriate for your use, please +** review the following information: +** http://trolltech.com/products/qt/licenses/licensing/licensingoverview +** or contact the sales department at sales@trolltech.com. +** +** This file may be used under the terms of the Q Public License as +** defined by Trolltech ASA and appearing in the file LICENSE.QPL +** included in the packaging of this file. Licensees holding valid Qt +** Commercial licenses may use this file in accordance with the Qt +** Commercial License Agreement provided with the Software. +** +** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, +** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted +** herein. +** +**********************************************************************/ + +/*! \page signalsandslots.html + +\title Signals and Slots + +Signals and slots are used for communication between objects. The +signal/slot mechanism is a central feature of Qt and probably the +part that differs most from other toolkits. + +In GUI programming we often want a change in one widget to be notified +to another widget. More generally, we want objects of any kind to be +able to communicate with one another. For example if we were parsing +an XML file we might want to notify a list view that we're using to +represent the XML file's structure whenever we encounter a new tag. + +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. + +\img abstract-connections.png +\caption An abstract view of some signals and slots connections + +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 pre-defined signals, but we can always subclass to +add our own. A slot is a function that is called in reponse to a +particular signal. Qt's widgets have many pre-defined slots, but it is +common practice to add your own slots so that you can handle the +signals that you are interested in. + +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 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 by +objects when they change their state in a way that may be interesting +to the outside world. 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. + +\img concrete-connections.png +\caption An example of signals and slots connections + +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 desire. 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: + +\code + class Foo + { + public: + Foo(); + int value() const { return val; } + void setValue( int ); + private: + int val; + }; +\endcode + +A small Qt class might read: + +\code + class Foo : public QObject + { + Q_OBJECT + public: + Foo(); + int value() const { return val; } + public slots: + void setValue( int ); + signals: + void valueChanged( int ); + private: + int val; + }; +\endcode + +This class has the same internal state, and 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 in +their declaration. + +Slots are implemented by the application programmer. +Here is a possible implementation of Foo::setValue(): + +\code + void Foo::setValue( int v ) + { + if ( v != val ) { + val = v; + emit valueChanged(v); + } + } +\endcode + +The line \c{emit valueChanged(v)} emits the signal +\c{valueChanged} from the object. As you can see, you emit a +signal by using \c{emit signal(arguments)}. + +Here is one way to connect two of these objects together: + +\code + Foo a, b; + connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int))); + b.setValue( 11 ); // a == undefined b == 11 + a.setValue( 79 ); // a == 79 b == 79 + b.value(); // returns 79 +\endcode + +Calling \c{a.setValue(79)} will make \c{a} emit a \c{valueChanged()} +signal, which \c{b} will receive in its \c{setValue()} slot, +i.e. \c{b.setValue(79)} is called. \c{b} will then, in turn, +emit the same \c{valueChanged()} signal, but since no slot has been +connected to \c{b}'s \c{valueChanged()} signal, nothing happens (the +signal is ignored). + +Note that the \c{setValue()} function sets the value and emits +the signal only if \c{v != val}. 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 \e{every} connection you make, so if you +duplicate a connection, two signals will be emitted. You can always +break a connection using \c{QObject::disconnect()}. + +This example illustrates that objects can work together without knowing +about each other, as long as there is someone around to set up a +connection between them initially. + +The preprocessor changes or removes the \c{signals}, \c{slots} and +\c{emit} keywords so that the compiler is presented with standard C++. + +Run the \link moc.html moc\endlink on class definitions that contain +signals or slots. This produces a C++ source file which should be compiled +and linked with the other object files for the application. If you use +\link qmake-manual.book qmake\endlink, the makefile rules to +automatically invoke the \link moc.html moc\endlink will be added to +your makefile for you. + +\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. + +A list box, for example, emits both \c{clicked()} and +\c{currentChanged()} signals. Most objects will probably only be +interested in \c{currentChanged()} which gives the current list item +whether the user clicked it or used the arrow keys to move to it. But +some objects may only want to know which item was clicked. If the +signal is interesting to two different objects you just connect the +signal to slots in both objects. + +When a signal is emitted, the slots connected to it are executed +immediately, just like a normal function call. The signal/slot +mechanism is totally independent of any GUI event loop. The +\c{emit} will return when all slots have returned. + +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 \link moc.html moc\endlink +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 \e not use special types. If \l +QScrollBar::valueChanged() were to use a special type such as the +hypothetical \c QRangeControl::Range, it could only be connected to +slots designed specifically for QRangeControl. Something as simple as +the program in \link tutorial1-05.html Tutorial #1 part 5\endlink +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. A slot's arguments +cannot have default values, and, like signals, it is rarely wise to +use your own custom types for slot arguments. + +Since slots are normal member functions with just a little extra +spice, they have access rights like ordinary member functions. A +slot's access right determines who can connect to it: + +A \c{public slots} section contains slots that anyone can connect +signals to. This is very useful for component programming: you create +objects that know nothing about each other, connect their signals and +slots so that information is passed correctly, and, like a model +railway, turn it on and leave it running. + +A \c{protected slots} section contains slots that this class and its +subclasses may connect signals to. This is intended for slots that are +part of the class's implementation rather than its interface to the +rest of the world. + +A \c{private slots} section contains slots that only the class itself +may connect signals to. This is intended for very tightly connected +classes, where even subclasses aren't trusted to get the connections +right. + +You can also define slots to be virtual, which we have found tquite +useful in practice. + +The signals and slots mechanism is efficient, but not tquite as fast as +"real" 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 retquired 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 retquires '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. 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. + + +\section1 Meta Object Information + +The meta object compiler (\link moc.html moc\endlink) 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. (For more +information on Qt's Meta Object System, see \link templates.html Why +doesn't Qt use templates for signals and slots?\endlink.) + +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: + +\code + if ( widget->inherits("QButton") ) { + // yes, it is a push button, radio button etc. + } +\endcode + +\section1 A Real Example + +Here is a simple commented example (code fragments from \l qlcdnumber.h ). + +\code + #include "qframe.h" + #include "qbitarray.h" + + class QLCDNumber : public QFrame +\endcode + +QLCDNumber inherits QObject, which has most of the signal/slot +knowledge, via QFrame and QWidget, and #include's the relevant +declarations. + +\code + { + Q_OBJECT +\endcode + +Q_OBJECT is expanded by the preprocessor to declare several member +functions that are implemented by the moc; if you get compiler errors +along the lines of "virtual function QButton::className not defined" +you have probably forgotten to \link moc.html run the moc\endlink or to +include the moc output in the link command. + +\code + public: + QLCDNumber( QWidget *parent=0, const char *name=0 ); + QLCDNumber( uint numDigits, QWidget *parent=0, const char *name=0 ); +\endcode + +It's not obviously relevant to the moc, but if you inherit QWidget you +almost certainly want to have the \e{parent} and \e{name} +arguments in your constructors, and pass them to the parent +constructor. + +Some destructors and member functions are omitted here; the moc +ignores member functions. + +\code + signals: + void overflow(); +\endcode + +QLCDNumber 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 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). + +\code + public slots: + void display( int num ); + void display( double num ); + void display( const char *str ); + void setHexMode(); + void setDecMode(); + void setOctMode(); + void setBinMode(); + void smallDecimalPoint( bool ); +\endcode + +A slot is a receiving function, used to get information about state +changes in other widgets. QLCDNumber 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 newValue() signal of a +QScrollBar to the display() slot, so the LCD number continuously shows +the value of the scroll bar. + +Note that 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. + +\code + }; +\endcode + +*/ |