[ fromfile: eventloop-revisited.xml id: eventloop-revisited ]
In Section 8.3 you met QApplication and the event loop. Now that you have had some experience with GUI programming, you are ready to look at events in more detail.
QWidget
s
send QEvent
s
to other QObject
s
in response to user actions such as mouse events and keyboard events.
A widget can also respond to events from the window manager such as repaints, resizes, or close events.
Events are posted (i.e., added to the event queue) and can be filtered and prioritized.
Furthermore, it is possible to post a custom event directly to any QObject
or selectively respond to events that were posted to other objects.
You can delegate the handling of an event to a specially defined handler object.
Each QWidget can be specialized
to respond to keyboard and mouse events in its own way.
Figure 9.23 is a screenshot of a QWidget named KeySequenceLabel
that captures a QKeySequence and
displays it for the user.
In Example 9.13 you can see from the names of
the private slots that QtCreator was used to compose the GUI.
Also, we chose the Multiple Inheritance option for embedding the Ui class,
so the KeySequenceLabel
class is derived from QMainWindow and from the
Designer generated Ui class.
Example 9.13. src/eventloop/keysequencelabel.h
[ . . . . ] #include "ui_keysequencelabel.h" #include <QList> #include <QPair> class QObjectBrowserAction; class KeySequenceLabel : public QMainWindow, private Ui::KeySequenceLabel { Q_OBJECT public: explicit KeySequenceLabel(QWidget* parent = 0); protected: void changeEvent(QEvent* e); void keyPressEvent(QKeyEvent*); void leaveEvent(QEvent*); void enterEvent(QEvent*); void paintEvent(QPaintEvent*); void timerEvent(QTimerEvent*); void updateUi(); private slots: void on_actionShow_ObjectBrowser_triggered(bool checked); void on_m_clearButton_clicked(); void on_actionQuit_triggered(); private: QObjectBrowserAction* m_browserAction; QList<QPair<int, int> > m_keys; int m_paints; }; [ . . . . ]
The implementation of this class contains some interesting items.
There is a QLabel in the dialog used for
display of a QKeySequence.
The QKeySequence class
encapsulates a sequence of up to four keystrokes, typically used as shortcuts to invoke QAction
s.
The base class keyPressEvent()
handler is overridden in the KeySequenceLabel
widget. In Example 9.14, you can see that it catches
the keystrokes and saves them to a list before the child widgets see them.
In updateUi()
, those events convert to a QKeySequence, and then
to a QString, which is sent to
the QLabel for display via setText()
.
Example 9.14. src/eventloop/keysequencelabel.cpp
[ . . . . ] void KeySequenceLabel::keyPressEvent(QKeyEvent* evt) { bool doNothing = false; if (evt->key() == 0) doNothing = true; if (m_keys.size() > 3) doNothing = true; if (doNothing) { QMainWindow::keyPressEvent(evt); return; } QPair<int, int> pair = QPair<int, int>(evt->modifiers(), evt->key()); m_keys << pair; evt->accept(); updateUi(); } void KeySequenceLabel::updateUi() { if (!m_keys.isEmpty()) { int keys[4] = {0,0,0,0}; for (int i=0; i<m_keys.size(); ++i) { QPair<int, int> pair = m_keys[i]; keys[i] = pair.first | pair.second; } QKeySequence seq = QKeySequence(keys[0], keys[1], keys[2], keys[3]); m_label->setText(seq.toString()); } else m_label->clear(); }
QWidget's base class handler responds to ESC for pop-up windows. |
We defined mouse event handlers, shown in Example 9.15, that tell you when the mouse pointer enters or leaves the widget.
Example 9.15. src/eventloop/keysequencelabel.cpp
In Example 9.16 the constructor makes use of
the QObject built-in timer and
calls QObject::startTimer()
,
which generates a timer event every 2 seconds.
We handle the timerEvent()
by updating a QLCDNumber, once every 2
seconds, with the number of paint events that have been performed so far.
For example, whenever the value of the LCDNumber changes, this indirectly causes the widget to repaint.
You can run this app and try moving and resizing the widget to see how it effects the number of paint
events.
Example 9.16. src/eventloop/keysequencelabel.cpp
[ . . . . ] KeySequenceLabel::KeySequenceLabel(QWidget* parent) : QMainWindow(parent), m_browserAction(new QObjectBrowserAction(this)) { setupUi(this); startTimer(2000); m_paints = 0; } void KeySequenceLabel::timerEvent(QTimerEvent*) { m_lcdNumber->display(m_paints); } void KeySequenceLabel::paintEvent(QPaintEvent* evt) { ++m_paints; QMainWindow::paintEvent(evt); }
All of the GUI activity discussed so far was accomplished with events and event handlers. There is another interesting feature of this example that is worth mentioning.
From the Tools
menu you can select Show ObjectBrowser
and see the widget in Figure 9.24.
QObjectBrowser
is an open source debugging tool that gives a graphic display of properties, signals, and slots of a QObject tree during the
execution of a program. [74]
One easy way to use it is by adding the QObjectBrowserAction
directly to the QMainWindow's menu.
A slightly modified version of this tool is included in src/libs.
[74] Contributed by Jeremy Magland, you can follow the development of this utility from its initial posting and see some community suggestions and the author's responses at http://tinyurl.com/2a6qkpy
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |