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.
764 lines
31 KiB
764 lines
31 KiB
/****************************************************************************
|
|
**
|
|
** Explanation of the Qt object model
|
|
**
|
|
** Copyright (C) 2000-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 requirements 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 object.html
|
|
|
|
\title Qt Object Model
|
|
|
|
The standard C++ Object Model provides very efficient runtime support
|
|
for the object paradigm. But the C++ Object Model's static nature is
|
|
inflexibile in certain problem domains. Graphical User Interface
|
|
programming is a domain that requires both runtime efficiency and a
|
|
high level of flexibility. Qt provides this, by combining the speed of
|
|
C++ with the flexibility of the Qt Object Model.
|
|
|
|
Qt adds these features to C++:
|
|
|
|
\list
|
|
\i a very powerful mechanism for seamless object
|
|
communication called \link signalsandslots.html signals and
|
|
slots \endlink;
|
|
\i queryable and designable \link properties.html object
|
|
properties \endlink;
|
|
\i powerful \link eventsandfilters.html events and event filters \endlink,
|
|
\i contextual \link i18n.html string translation for internationalization \endlink;
|
|
\i sophisticated interval driven \link timers.html timers \endlink
|
|
that make it possible to elegantly integrate many tasks in an
|
|
event-driven GUI;
|
|
\i hierarchical and queryable \link objecttrees.html object
|
|
trees \endlink that organize object ownership in a natural way;
|
|
\i guarded pointers, \l QGuardedPtr, that are automatically
|
|
set to 0 when the referenced object is destroyed, unlike normal C++
|
|
pointers which become "dangling pointers" when their objects are destroyed.
|
|
\endlist
|
|
|
|
Many of these Qt features are implemented with standard C++
|
|
techniques, based on inheritance from \l QObject. Others, like the
|
|
object communication mechanism and the dynamic property system,
|
|
require the \link metaobjects.html Meta Object System \endlink provided
|
|
by Qt's own \link moc.html Meta Object Compiler (moc) \endlink.
|
|
|
|
The Meta Object System is a C++ extension that makes the language
|
|
better suited to true component GUI programming. Although templates can
|
|
be used to extend C++, the Meta Object System provides benefits using
|
|
standard C++ that cannot be achieved with templates; see \link
|
|
templates.html Why doesn't Qt use templates for signals and
|
|
slots? \endlink.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
\page timers.html
|
|
|
|
\title Timers
|
|
|
|
\l QObject, the base class of all Qt objects, provides the basic timer
|
|
support in Qt. With \l QObject::startTimer(), you start a timer with
|
|
an \e interval in milliseconds as argument. The function returns a
|
|
unique integer timer id. The timer will now "fire" every \e interval
|
|
milliseconds, until you explicitly call \l QObject::killTimer() with
|
|
the timer id.
|
|
|
|
For this mechanism to work, the application must run in an event
|
|
loop. You start an event loop with \l QApplication::exec(). When a
|
|
timer fires, the application sends a QTimerEvent, and the flow of
|
|
control leaves the event loop until the timer event is processed. This
|
|
implies that a timer cannot fire while your application is busy doing
|
|
something else. In other words: the accuracy of timers depends on the
|
|
granularity of your application.
|
|
|
|
There is practically no upper limit for the interval value (more than
|
|
one year is possible). The accuracy depends on the underlying operating
|
|
system. Windows 95/98 has 55 millisecond (18.2 times per second)
|
|
accuracy; other systems that we have tested (UNIX X11 and Windows NT)
|
|
can handle 1 millisecond intervals.
|
|
|
|
The main API for the timer functionality is \l QTimer. That class
|
|
provides regular timers that emit a signal when the timer fires, and
|
|
inherits \l QObject so that it fits well into the ownership structure
|
|
of most GUI programs. The normal way of using it is like this:
|
|
\code
|
|
QTimer * counter = new QTimer( this );
|
|
connect( counter, SIGNAL(timeout()),
|
|
this, SLOT(updateCaption()) );
|
|
counter->start( 1000 );
|
|
\endcode
|
|
|
|
The counter timer is made into a child of this widget, so that when
|
|
this widget is deleted, the timer is deleted too. Next, its timeout
|
|
signal is connected to the slot that will do the work, and finally
|
|
it's started.
|
|
|
|
QTimer also provides a simple one-shot timer API. \l QButton uses this
|
|
to show the button being pressed down and then (0.1 seconds later) be
|
|
released when the keyboard is used to "press" a button, for example:
|
|
|
|
\code
|
|
QTimer::singleShot( 100, this, SLOT(animateTimeout()) );
|
|
\endcode
|
|
|
|
0.1 seconds after this line of code is executed, the same button's
|
|
animateTimeout() slot is called.
|
|
|
|
Here is an outline of a slightly longer example that combines object
|
|
communication via signals and slots with a QTimer object. It
|
|
demonstrates how to use timers to perform intensive calculations in a
|
|
single-threaded application without blocking the user interface.
|
|
|
|
\code
|
|
// The Mandelbrot class uses a QTimer to calculate the mandelbrot
|
|
// set one scanline at a time without blocking the CPU. It
|
|
// inherits QObject to use signals and slots. Calling start()
|
|
// starts the calculation. The done() signal is emitted when it
|
|
// has finished. Note that this example is not complete, just an
|
|
// outline.
|
|
|
|
class Mandelbrot : public QObject
|
|
{
|
|
TQ_OBJECT // required for signals/slots
|
|
public:
|
|
Mandelbrot( QObject *parent=0, const char *name );
|
|
...
|
|
public slots:
|
|
void start();
|
|
signals:
|
|
void done();
|
|
private slots:
|
|
void calculate();
|
|
private:
|
|
QTimer timer;
|
|
...
|
|
};
|
|
|
|
//
|
|
// Constructs and initializes a Mandelbrot object.
|
|
//
|
|
|
|
Mandelbrot::Mandelbrot( QObject *parent=0, const char *name )
|
|
: QObject( parent, name )
|
|
{
|
|
connect( &timer, SIGNAL(timeout()), SLOT(calculate()) );
|
|
...
|
|
}
|
|
|
|
//
|
|
// Starts the calculation task. The internal calculate() slot
|
|
// will be activated every 10 milliseconds.
|
|
//
|
|
|
|
void Mandelbrot::start()
|
|
{
|
|
if ( !timer.isActive() ) // not already running
|
|
timer.start( 10 ); // timeout every 10 ms
|
|
}
|
|
|
|
//
|
|
// Calculates one scanline at a time.
|
|
// Emits the done() signal when finished.
|
|
//
|
|
|
|
void Mandelbrot::calculate()
|
|
{
|
|
... // perform the calculation for a scanline
|
|
if ( finished ) { // no more scanlines
|
|
timer.stop();
|
|
emit done();
|
|
}
|
|
}
|
|
\endcode
|
|
|
|
|
|
*/
|
|
|
|
|
|
/*!
|
|
\page properties.html
|
|
|
|
\title Properties
|
|
|
|
Qt provides a sophisticated property system similar to those supplied
|
|
by some compiler vendors. However, as a compiler- and
|
|
platform-independent library, Qt cannot rely on non-standard compiler
|
|
features like \c __property or \c [property]. Our solution works with
|
|
\e any standard C++ compiler on every platform we support. It's based
|
|
on the meta-object system that also provides object communication
|
|
through \link signalsandslots.html signals and slots\endlink.
|
|
|
|
The \c Q_PROPERTY macro in a class declaration declares a
|
|
property. Properties can only be declared in classes that inherit \l
|
|
QObject. A second macro, \c Q_OVERRIDE, can be used to override some
|
|
aspects of an inherited property in a subclass. (See \link #override
|
|
Q_OVERRIDE\endlink.)
|
|
|
|
To the outer world, a property appears to be similar to a data member.
|
|
But properties have several features that distinguish them from
|
|
ordinary data members:
|
|
|
|
\list
|
|
\i A read function. This always exists.
|
|
|
|
\i A write function. This is optional: read-only properties like \l
|
|
QWidget::isDesktop() do not have one.
|
|
|
|
\i An attribute "stored" that indicates persistence. Most properties
|
|
are stored, but a few virtual properties are not. For example, \l
|
|
QWidget::minimumWidth() isn't stored, since it's just a view of
|
|
\l QWidget::minimumSize(), and has no data of its own.
|
|
|
|
\i A reset function to set a property back to its context specific
|
|
default value. This is very rare, but for example, \l QWidget::font()
|
|
needs this, since no call to \l QWidget::setFont() can mean 'reset to
|
|
the context specific font'.
|
|
|
|
\i An attribute "designable" that indicates whether it makes sense to
|
|
make the property available in a GUI builder (e.g. \link
|
|
designer-manual.book Qt Designer\endlink). For most properties this
|
|
makes sense, but not for all, e.g. \l QButton::isDown(). The user can
|
|
press buttons, and the application programmer can make the program
|
|
press its own buttons, but a GUI design tool can't press buttons.
|
|
|
|
\endlist
|
|
|
|
The read, write, and reset functions must be public member functions
|
|
from the class in which the property is defined.
|
|
|
|
Properties can be read and written through generic functions in
|
|
QObject without knowing anything about the class in use. These two
|
|
function calls are equivalent:
|
|
|
|
\code
|
|
// QButton *b and QObject *o point to the same button
|
|
b->setDown( TRUE );
|
|
o->setProperty( "down", TRUE );
|
|
\endcode
|
|
|
|
Equivalent, that is, except that the first is faster, and provides
|
|
much better diagnostics at compile time. When practical, the first is
|
|
better. However, since you can get a list of all available properties
|
|
for any QObject through its \l QMetaObject, \l QObject::setProperty()
|
|
can give you control over classes that weren't available at compile
|
|
time.
|
|
|
|
As well as QObject::setProperty(), there is a corresponding \l
|
|
QObject::property() function. \l QMetaObject::propertyNames() returns
|
|
the names of all available properties. \l QMetaObject::property()
|
|
returns the property data for a named property: a \l QMetaProperty
|
|
object.
|
|
|
|
Here's a simple example that shows the most important property
|
|
functions in use:
|
|
|
|
\code
|
|
class MyClass : public QObject
|
|
{
|
|
TQ_OBJECT
|
|
public:
|
|
MyClass( QObject * parent=0, const char * name=0 );
|
|
~MyClass();
|
|
|
|
enum Priority { High, Low, VeryHigh, VeryLow };
|
|
void setPriority( Priority );
|
|
Priority priority() const;
|
|
};
|
|
\endcode
|
|
|
|
The class has a property "priority" that is not yet known to the meta
|
|
object system. In order to make the property known, you must
|
|
declare it with the \c Q_PROPERTY macro. The syntax is as follows:
|
|
|
|
\code
|
|
Q_PROPERTY( type name READ getFunction [WRITE setFunction]
|
|
[RESET resetFunction] [DESIGNABLE bool]
|
|
[SCRIPTABLE bool] [STORED bool] )
|
|
\endcode
|
|
|
|
For the declaration to be valid, the get function must be const and
|
|
to return either the type itself, a pointer to it, or a reference to
|
|
it. The optional write function must return void and must take exactly
|
|
one argument, either the type itself, a pointer or a const reference
|
|
to it. The meta object compiler enforces this.
|
|
|
|
The type of a property can be any \l QVariant supported type or an
|
|
enumeration type declared in the class itself. Since \c MyClass uses
|
|
the enumeration type \c Priority for the property, this type must be
|
|
registered with the property system as well.
|
|
|
|
There are two exceptions to the above: The type of a property can also
|
|
be either \link QValueList QValueList\<QVariant\>\endlink or \link
|
|
QMap QMap\<QString,QVariant\>\endlink. In
|
|
these cases the type must be specified as \c QValueList or as \c QMap
|
|
(i.e. without their template parameters).
|
|
|
|
It is possible to set a value by name, like this:
|
|
\code
|
|
obj->setProperty( "priority", "VeryHigh" );
|
|
\endcode
|
|
In the case of \c QValueList and \c QMap properties the value passes
|
|
is a QVariant whose value is the entire list or map.
|
|
|
|
Enumeration types are registered with the \c Q_ENUMS macro. Here's the
|
|
final class declaration including the property related declarations:
|
|
|
|
\code
|
|
class MyClass : public QObject
|
|
{
|
|
TQ_OBJECT
|
|
Q_PROPERTY( Priority priority READ priority WRITE setPriority )
|
|
Q_ENUMS( Priority )
|
|
public:
|
|
MyClass( QObject * parent=0, const char * name=0 );
|
|
~MyClass();
|
|
|
|
enum Priority { High, Low, VeryHigh, VeryLow };
|
|
void setPriority( Priority );
|
|
Priority priority() const;
|
|
};
|
|
\endcode
|
|
|
|
Another similar macro is \c Q_SETS. Like \c Q_ENUMS, it registers an
|
|
enumeration type but marks it in addition as a "set", i.e. the
|
|
enumeration values can be OR-ed together. An I/O class might have
|
|
enumeration values "Read" and "Write" and accept "Read|Write": such an
|
|
enum is best handled with \c Q_SETS, rather than \c Q_ENUMS.
|
|
|
|
The remaining keywords in the \c Q_PROPERTY section are \c RESET, \c
|
|
DESIGNABLE, \c SCRIPTABLE and \c STORED.
|
|
|
|
\c RESET names a function that will set the property to its default
|
|
state (which may have changed since initialization). The function
|
|
must return void and take no arguments.
|
|
|
|
\c DESIGNABLE declares whether this property is suitable for
|
|
modification by a GUI design tool. The default is \c TRUE for
|
|
writable properties; otherwise \c FALSE. Instead of \c TRUE or \c
|
|
FALSE, you can specify a boolean member function.
|
|
|
|
\c SCRIPTABLE declares whether this property is suited for access by a
|
|
scripting engine. The default is \c TRUE. Instead of \c TRUE or \c FALSE,
|
|
you can specify a boolean member function.
|
|
|
|
\c STORED declares whether the property's value must be remembered
|
|
when storing an object's state. Stored makes only sense for writable
|
|
properties. The default value is \c TRUE. Technically superfluous
|
|
properties (like QPoint pos if QRect geometry is already a property)
|
|
define this to be \c FALSE.
|
|
|
|
|
|
Connected to the property system is an additional macro, "Q_CLASSINFO",
|
|
that can be used to attach additional name/value-pairs to a class'
|
|
meta object, for example:
|
|
|
|
\code
|
|
Q_CLASSINFO( "Version", "3.0.0" )
|
|
\endcode
|
|
|
|
Like other meta data, class information is accessible at runtime
|
|
through the meta object, see \l QMetaObject::classInfo() for details.
|
|
|
|
\target override
|
|
\section1 Q_OVERRIDE
|
|
|
|
When you inherit a QObject subclass you may wish to override some
|
|
aspects of some of the class's properties.
|
|
|
|
For example, in QWidget we have the autoMask property defined like
|
|
this:
|
|
\code
|
|
Q_PROPERTY( bool autoMask READ autoMask WRITE setAutoMask DESIGNABLE false SCRIPTABLE false )
|
|
\endcode
|
|
|
|
But we need to make the auto mask property designable in some QWidget
|
|
subclasses. Similarly some classes will need this property to be
|
|
scriptable (e.g. for QSA). This is achieved by overriding these
|
|
features of the property in a subclass. In QCheckBox, for example, we
|
|
achieve this using the following code:
|
|
\code
|
|
Q_OVERRIDE( bool autoMask DESIGNABLE true SCRIPTABLE true )
|
|
\endcode
|
|
|
|
Another example is QToolButton. By default QToolButton has a read-only
|
|
"toggleButton" property, because that's what it inherits from QButton:
|
|
\code
|
|
Q_PROPERTY( bool toggleButton READ isToggleButton )
|
|
\endcode
|
|
|
|
But we want to make our tool buttons able to be toggled, so we write a
|
|
WRITE function in QToolButton, and use the following property override
|
|
to make it acessible:
|
|
\code
|
|
Q_OVERRIDE( bool toggleButton WRITE setToggleButton )
|
|
\endcode
|
|
The result is read-write (and scriptable and designable, since we now
|
|
have a WRITE function) boolean property "toggleButton" for tool
|
|
buttons.
|
|
|
|
*/
|
|
|
|
/*!
|
|
\page eventsandfilters.html
|
|
|
|
\title Events and Event Filters
|
|
|
|
In Qt, an event is an object that inherits \l QEvent. Events are
|
|
delivered to objects that inherit \l QObject through calling \l
|
|
QObject::event(). Event delivery means that an event has occurred, the
|
|
QEvent indicates precisely what, and the QObject needs to respond. Most
|
|
events are specific to \l QWidget and its subclasses, but there are
|
|
important events that aren't related to graphics, for example, socket
|
|
activation, which is the event used by \l QSocketNotifier for its
|
|
work.
|
|
|
|
Some events come from the window system, e.g. \l QMouseEvent, some
|
|
from other sources, e.g. \l QTimerEvent, and some come from the
|
|
application program. Qt is symmetric, as usual, so you can send
|
|
events in exactly the same ways as Qt's own event loop does.
|
|
|
|
Most events types have special classes, most commonly \l QResizeEvent,
|
|
\l QPaintEvent, \l QMouseEvent, \l QKeyEvent and \l QCloseEvent.
|
|
There are many others, perhaps forty or so, but most are rather odd.
|
|
|
|
Each class subclasses QEvent and adds event-specific functions; see,
|
|
for example, \l QResizeEvent. In the case of QResizeEvent, \l
|
|
QResizeEvent::size() and \l QResizeEvent::oldSize() are added.
|
|
|
|
Some classes support more than one event type. \l QMouseEvent
|
|
supports mouse moves, presses, shift-presses, drags, clicks,
|
|
right-presses, etc.
|
|
|
|
Since programs need to react in varied and complex ways, Qt's
|
|
event delivery mechanisms are flexible. The documentation for
|
|
\l QApplication::notify() concisely tells the whole story, here we
|
|
will explain enough for 99% of applications.
|
|
|
|
The normal way for an event to be delivered is by calling a virtual
|
|
function. For example, \l QPaintEvent is delivered by calling \l
|
|
QWidget::paintEvent(). This virtual function is responsible for
|
|
reacting appropriately, normally by repainting the widget. If you
|
|
do not perform all the necessary work in your implementation of the
|
|
virtual function, you may need to call the base class's
|
|
implementation; for example:
|
|
\code
|
|
MyTable::contentsMouseMoveEvent( QMouseEvent *me )
|
|
{
|
|
// my implementation
|
|
|
|
QTable::contentsMouseMoveEvent( me ); // hand it on
|
|
}
|
|
\endcode
|
|
If you want to replace the base class's function then you must
|
|
implement everything yourself; but if you only want to extend the base
|
|
class's functionality, then you implement what you want and then call
|
|
the base class.
|
|
|
|
Occasionally there isn't such an event-specific function, or the
|
|
event-specific function isn't sufficient. The most common example is
|
|
tab key presses. Normally, those are interpreted by QWidget to move
|
|
the keyboard focus, but a few widgets need the tab key for themselves.
|
|
|
|
These objects can reimplement \l QObject::event(), the general event
|
|
handler, and either do their event handling before or after the usual
|
|
handling, or replace it completely. A very unusual widget that both
|
|
interprets tab and has an application-specific custom event might
|
|
contain:
|
|
|
|
\code
|
|
bool MyClass:event( QEvent *evt ) {
|
|
if ( evt->type() == QEvent::KeyPress ) {
|
|
QKeyEvent *ke = (QKeyEvent *)evt;
|
|
if ( ke->key() == Key_Tab ) {
|
|
// special tab handling here
|
|
ke->accept();
|
|
return TRUE;
|
|
}
|
|
} else if ( evt->type() >= QEvent::User ) {
|
|
QCustomEvent *ce = (QCustomEvent*) evt;
|
|
// custom event handling here
|
|
return TRUE;
|
|
}
|
|
return QWidget::event( evt );
|
|
}
|
|
\endcode
|
|
|
|
More commonly, an object needs to look at another's events. Qt
|
|
supports this using \l QObject::installEventFilter() (and the
|
|
corresponding remove). For example, dialogs commonly want to filter
|
|
key presses for some widgets, e.g. to modify Return-key handling.
|
|
|
|
An event filter gets to process events before the target object does.
|
|
The filter's \l QObject::eventFilter() implementation is called, and
|
|
can accept or reject the filter, and allow or deny further processing
|
|
of the event. If all the event filters allow further processing of an
|
|
event, the event is sent to the target object itself. If one of them
|
|
stops processing, the target and any later event filters don't get to
|
|
see the event at all.
|
|
|
|
It's also possible to filter \e all events for the entire application,
|
|
by installing an event filter on \l QApplication. This is what \l
|
|
QToolTip does in order to see \e all the mouse and keyboard activity.
|
|
This is very powerful, but it also slows down event delivery of every
|
|
single event in the entire application, so it's best avoided.
|
|
|
|
The global event filters are called before the object-specific
|
|
filters.
|
|
|
|
Finally, many applications want to create and send their own events.
|
|
|
|
Creating an event of a built-in type is very simple: create an object
|
|
of the relevant type, and then call \l QApplication::sendEvent() or \l
|
|
QApplication::postEvent().
|
|
|
|
sendEvent() processes the event immediately - when sendEvent()
|
|
returns, (the event filters and) the object have already processed the
|
|
event. For many event classes there is a function called isAccepted()
|
|
that tells you whether the event was accepted or rejected by the last
|
|
handler that was called.
|
|
|
|
postEvent() posts the event on a queue for later dispatch. The next
|
|
time Qt's main event loop runs, it dispatches all posted events, with
|
|
some optimization. For example, if there are several resize events,
|
|
they are are compacted into one. The same applies to paint events: \l
|
|
QWidget::update() calls postEvent(), which minimizes flickering and
|
|
increases speed by avoiding multiple repaints.
|
|
|
|
postEvent() is also often used during object initialization, since the
|
|
posted event will typically be dispatched very soon after the
|
|
initialization of the object is complete.
|
|
|
|
To create events of a custom type, you need to define an event number,
|
|
which must be greater than \c QEvent::User, and probably you also need
|
|
to subclass \l QCustomEvent in order to pass characteristics about
|
|
your custom event. See the documentation to \l QCustomEvent for
|
|
details.
|
|
|
|
*/
|
|
|
|
|
|
/*!
|
|
\page objecttrees.html
|
|
|
|
\title Object Trees and Object Ownership
|
|
|
|
\link QObject QObjects\endlink organize themselves in object trees.
|
|
When you create a QObject with another object as parent, it's added to
|
|
the parent's \link QObject::children() children() \endlink list, and
|
|
is deleted when the parent is. It turns out that this approach fits
|
|
the needs of GUI objects very well. For example, a \l QAccel (keyboard
|
|
accelerator) is a child of the relevant window, so when the user closes
|
|
that window, the accelerator is deleted too.
|
|
|
|
The static function \l QObject::objectTrees() provides access to all
|
|
the root objects that currently exist.
|
|
|
|
\l QWidget, the base class of everything that appears on the screen,
|
|
extends the parent-child relationship. A child normally also becomes a
|
|
child widget, i.e. it is displayed in its parent's coordinate system
|
|
and is graphically clipped by its parent's boundaries. For example,
|
|
when the an application deletes a message box after it has been
|
|
closed, the message box's buttons and label are also deleted, just as
|
|
we'd want, because the buttons and label are children of the message
|
|
box.
|
|
|
|
You can also delete child objects yourself, and they will remove
|
|
themselves from their parents. For example, when the user removes a
|
|
toolbar it may lead to the application deleting one of its \l QToolBar
|
|
objects, in which case the tool bar's \l QMainWindow parent would
|
|
detect the change and reconfigure its screen space accordingly.
|
|
|
|
The debugging functions \l QObject::dumpObjectTree() and \l
|
|
QObject::dumpObjectInfo() are often useful when an application looks or
|
|
acts strangely.
|
|
|
|
*/
|
|
|
|
|
|
/*!
|
|
\page templates.html
|
|
|
|
\title Why doesn't Qt use templates for signals and slots?
|
|
|
|
A simple answer is that when Qt was designed, it was not possible to
|
|
fully exploit the template mechanism in multi-platform applications due
|
|
to the inadequacies of various compilers. Even today, many widely used
|
|
C++ compilers have problems with advanced templates. For example, you
|
|
cannot safely rely on partial template instantiation, which is essential
|
|
for some non-trivial problem domains. Thus Qt's usage of templates has
|
|
to be rather conservative. Keep in mind that Qt is a multi-platform
|
|
toolkit, and progress on the Linux/g++ platform does not necessarily
|
|
improve the situation elsewhere.
|
|
|
|
Eventually those compilers with weak template implementations will
|
|
improve. But even if all our users had access to a fully standards
|
|
compliant modern C++ compiler with excellent template support, we would
|
|
not abandon the string-based approach used by our meta object compiler.
|
|
Here are five reasons why:
|
|
|
|
<h3>1. Syntax matters</h3>
|
|
|
|
Syntax isn't just sugar: the syntax we use to express our algorithms can
|
|
significantly affect the readability and maintainability of our code.
|
|
The syntax used for Qt's signals and slots has proved very successful in
|
|
practice. The syntax is intuitive, simple to use and easy to read.
|
|
People learning Qt find the syntax helps them understand and utilize the
|
|
signals and slots concept -- despite its highly abstract and generic
|
|
nature. Furthermore, declaring signals in class definitions ensures that
|
|
the signals are protected in the sense of protected C++ member
|
|
functions. This helps programmers get their design right from the very
|
|
beginning, without even having to think about design patterns.
|
|
|
|
<h3>2. Precompilers are good</h3>
|
|
|
|
Qt's <tt>moc</tt> (Meta Object Compiler) provides a clean way to go
|
|
beyond the compiled language's facilities. It does so by generating
|
|
additional C++ code which can be compiled by any standard C++ compiler.
|
|
The <tt>moc</tt> reads C++ source files. If it finds one or more class
|
|
declarations that contain the "TQ_OBJECT" macro, it produces another C++
|
|
source file which contains the meta object code for those classes. The
|
|
C++ source file generated by the <tt>moc</tt> must be compiled and
|
|
linked with the implementation of the class (or it can be
|
|
<tt>#included</tt> into the class's source file). Typically <tt>moc</tt>
|
|
is not called manually, but automatically by the build system, so it
|
|
requires no additional effort by the programmer.
|
|
|
|
There are other precompilers, for example, <tt>rpc</tt> and
|
|
<tt>idl</tt>, that enable programs or objects to communicate over
|
|
process or machine boundaries. The alternatives to precompilers are
|
|
hacked compilers, proprietary languages or graphical programming tools
|
|
with dialogs or wizards that generate obscure code. Rather than locking
|
|
our customers into a proprietary C++ compiler or into a particular
|
|
Integrated Development Environment, we enable them to use whatever tools
|
|
they prefer. Instead of forcing programmers to add generated code into
|
|
source repositories, we encourage them to add our tools to their build
|
|
system: cleaner, safer and more in the spirit of UNIX.
|
|
|
|
|
|
<h3>3. Flexibility is king</h3>
|
|
|
|
C++ is a standarized, powerful and elaborate general-purpose language.
|
|
It's the only language that is exploited on such a wide range of
|
|
software projects, spanning every kind of application from entire
|
|
operating systems, database servers and high end graphics
|
|
applications to common desktop applications. One of the keys to C++'s
|
|
success is its scalable language design that focuses on maximum
|
|
performance and minimal memory consumption whilst still maintaining
|
|
ANSI-C compatibility.
|
|
|
|
For all these advantages, there are some downsides. For C++, the static
|
|
object model is a clear disadvantage over the dynamic messaging approach
|
|
of Objective C when it comes to component-based graphical user interface
|
|
programming. What's good for a high end database server or an operating
|
|
system isn't necessarily the right design choice for a GUI frontend.
|
|
With <tt>moc</tt>, we have turned this disadvantage into an advantage,
|
|
and added the flexibility required to meet the challenge of safe and
|
|
efficient graphical user interface programming.
|
|
|
|
Our approach goes far beyond anything you can do with templates. For
|
|
example, we can have object properties. And we can have overloaded
|
|
signals and slots, which feels natural when programming in a language
|
|
where overloads are a key concept. Our signals add zero bytes to the
|
|
size of a class instance, which means we can add new signals without
|
|
breaking binary compatibility. Because we do not rely on excessive
|
|
inlining as done with templates, we can keep the code size smaller.
|
|
Adding new connections just expands to a simple function call rather
|
|
than a complex template function.
|
|
|
|
Another benefit is that we can explore an object's signals and slots at
|
|
runtime. We can establish connections using type-safe call-by-name,
|
|
without having to know the exact types of the objects we are connecting.
|
|
This is impossible with a template based solution. This kind of runtime
|
|
introspection opens up new possibilities, for example GUIs that are
|
|
generated and connected from Qt Designer's XML <tt>ui</tt> files.
|
|
|
|
<h3>4. Calling performance is not everything</h3>
|
|
|
|
Qt's signals and slots implementation is not as fast as a template-based
|
|
solution. While emitting a signal is approximately the cost of four
|
|
ordinary function calls with common template implementations, Qt
|
|
requires effort comparable to about ten function calls. This is not
|
|
surprising since the Qt mechanism includes a generic marshaller,
|
|
introspection and ultimately scriptability. It does not rely on
|
|
excessive inlining and code expansion and it provides unmatched runtime
|
|
safety. Qt's iterators are safe while those of faster template-based
|
|
systems are not. Even during the process of emitting a signal to several
|
|
receivers, those receivers can be deleted safely without your program
|
|
crashing. Without this safety, your application would eventually crash
|
|
with a difficult to debug free'd memory read or write error.
|
|
|
|
Nonetheless, couldn't a template-based solution improve the performance
|
|
of an application using signals and slots? While it is true that Qt adds
|
|
a small overhead to the cost of calling a slot through a signal, the
|
|
cost of the call is only a small proportion of the entire cost of a
|
|
slot. Benchmarking against Qt's signals and slots system is typically
|
|
done with empty slots. As soon as you do anything useful in your slots,
|
|
for example a few simple string operations, the calling overhead becomes
|
|
negligible. Qt's system is so optimized that anything that requires
|
|
operator new or delete (for example, string operations or
|
|
inserting/removing something from a template container) is significantly
|
|
more expensive than emitting a signal.
|
|
|
|
Aside: If you have a signals and slots connection in a tight inner loop
|
|
of a performance critical task and you identify this connection as the
|
|
bottleneck, think about using the standard listener-interface pattern
|
|
rather than signals and slots. In cases where this occurs, you probably
|
|
only require a 1:1 connection anyway. For example, if you have an object
|
|
that downloads data from the network, it's a perfectly sensible design
|
|
to use a signal to indicate that the requested data arrived. But if you
|
|
need to send out every single byte one by one to a consumer, use a
|
|
listener interface rather than signals and slots.
|
|
|
|
<h3>5. No limits</h3>
|
|
|
|
Because we had the <tt>moc</tt> for signals and slots, we could add
|
|
other useful things to it that could not not be done with templates.
|
|
Among these are scoped translations via a generated <tt>tr()</tt>
|
|
function, and an advanced property system with introspection and
|
|
extended runtime type information. The property system alone is a great
|
|
advantage: a powerful and generic user interface design tool like Qt
|
|
Designer would be a lot harder to write - if not impossible - without a
|
|
powerful and introspective property system.
|
|
|
|
C++ with the <tt>moc</tt> preprocessor essentially gives us the
|
|
flexibility of Objective-C or of a Java Runtime Environment, while
|
|
maintaining C++'s unique performance and scalability advantages. It is
|
|
what makes Qt the flexible and comfortable tool we have today.
|
|
|
|
*/
|