You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
16 KiB
411 lines
16 KiB
/****************************************************************************
|
|
**
|
|
** 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 quite
|
|
useful 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 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
|
|
|
|
*/
|