Qt Events
Objectives
- Understand the concept of events
- Understand the difference between events and signal/slots
- Be able to implement event handling
- Understand the role of events in painting
- Understand the role of event filters and be able to use them
- Understand the concept of event propagation
- Learn how to post/send events
- Be able to create/send/handle custom events
Qt Events
- In Qt, events are objects that represent things that have happened either within an application or as a result of outside activity that the application needs to know about.
- When an event occurs, Qt creates an event object to represent it and delivers it to a particular instance of QObject (or a subclass) by calling its {{event()} function.
- This function calls an event handler for the specific event.
- Three categories:
- Spontaneous events are generated by the window system. They are put in a system queue and processed one after the other by the event loop.
- Posted events are generated by Qt or by the application. They are queued by Qt and processed by the event loop.
- Sent events are generated by Qt or by the application, but they are sent directly to the target object.
- Events are useful when we write our own widgets or we want to modify the behavior of existing widgets.
Difference between events and signal/slots
- Events and signal/slots are two parallel mechanisms that can accomplish the same thing.
- An event will be generated by an outside entity and will be delivered through the event loop in QApplication.
- Signal/slots will be used by the interclass communication
- You handle events but you get notified by signal emissions.
- Signals are useful when using a widget, whereas events are useful when implementing a widget.
Key Events
- Key events are handled by re-implementing keyPressEvent() and keyReleaseEvent().
- Key names used by Qt
Example: Handling the ESC key.
keypress.h
#ifndef KEYPRESS_H #define KEYPRESS_H #include <QWidget> #include <QtGui> class KeyPress : public QWidget { Q_OBJECT public: KeyPress(QWidget *parent = 0); protected: void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); private: QLabel *myLabel; QVBoxLayout *mainLayout; }; #endif // KEYPRESS_H
keypress.cpp
#include "keypress.h" #include <QApplication> #include <QKeyEvent> KeyPress::KeyPress(QWidget *parent) : QWidget(parent) { myLabel = new QLabel("LABEL"); mainLayout = new QVBoxLayout; mainLayout->addWidget(myLabel); setLayout(mainLayout); } void KeyPress::keyPressEvent(QKeyEvent *event) { if(event->key() == Qt::Key_Escape) { myLabel->setText("You pressed ESC"); } } void KeyPress::keyReleaseEvent(QKeyEvent *event) { if(event->key() == Qt::Key_Escape) { myLabel->setText("You released ESC"); } }
main.cpp
#include <QtGui> #include "keypress.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); KeyPress *keyPress = new KeyPress(); keyPress->show(); return a.exec(); }
Timer Events
- Timer events allow applications to perform processing at regular time intervals
- The QTimer class provides an interface for timers. To use it:
- Create a QTimer
- connect its timeout() signal to the appropriate slots
- call start()
- From then on it will emit the timeout() signal at constant intervals.
Example: Simple Counter
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QtGui> #include <QMainWindow> class MainWindow : public QWidget { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: QPushButton *myButton; QLabel *myLabel; QTimer *myTimer; int timerCount; private slots: void changeText(); void timerTimeout(); }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QTime> MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { myButton = new QPushButton("Start Timer"); myLabel = new QLabel("100"); QVBoxLayout *myLayout = new QVBoxLayout; myLayout->addWidget(myButton); myLayout->addWidget(myLabel); setLayout(myLayout); myTimer = new QTimer(this); myTimer->setInterval(10); timerCount = 0; connect(myButton, SIGNAL(clicked()), this, SLOT(changeText())); connect(myTimer, SIGNAL(timeout()), this, SLOT(timerTimeout())); } MainWindow::~MainWindow() { } void MainWindow::changeText() { myButton->setEnabled(false); timerCount = 100; if(!myTimer->isActive()) myTimer->start(); } void MainWindow::timerTimeout() { myLabel->setText(QString::number(timerCount)); --timerCount; if (timerCount <= 0) { myTimer->stop(); myButton->setEnabled(true); myLabel->setText(QString::number(100)); } }
main.cpp
#include <QtGui/QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.adjustSize(); w.move(QApplication::desktop()->screen()->rect().center() - w.rect().center()); w.show(); return a.exec(); }
Role of events in painting
- There are situations, when we need to create a widget from scratch. In such a case, we need to do painting.
- The QPainter class is instrumental when we do some painting in the Qt4 programming library. The paining is done with the QPainter class inside the paintEvent() method.
- paintEvent() is called whenever the widget needs to be repainted. Every widget displaying custom content must implement it. Painting using a QPainter can only take place in a paintEvent() or a function called by a paintEvent().
Event Filters
a QObject instance can
- A QObject instance can be set to monitor the events of another QObject instance before the latter object even sees them.
- Setting up an event filter involves two steps:
- Register the monitoring object with the target object by calling installEventFilter() on the target.
- Handle the target object’s events in the monitor’s eventFilter() function
Example: Filter numbers from QLineEdit.
KeyboardFilter.h
#ifndef KEYBOARDFILTER_H #define KEYBOARDFILTER_H #include <QApplication> #include <QLineEdit> #include <QKeyEvent> class KeyboardFilter : public QObject { public: KeyboardFilter( QObject *parent = 0 ) : QObject( parent ) {} protected: bool eventFilter( QObject *dist, QEvent *event ); }; #endif // KEYBOARDFILTER_H
keyboardFilter.cpp
#include "KeyboardFilter.h" bool KeyboardFilter::eventFilter( QObject *dist, QEvent *event ) { if( event->type() == QEvent::KeyPress ) { QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event ); if( QString("1234567890").indexOf( keyEvent->text() ) != -1 ) return true; } return false; }
main.cpp
#include <QtGui> #include "KeyboardFilter.h" int main( int argc, char **argv ) { QApplication app( argc, argv ); QLineEdit lineEdit; KeyboardFilter filter; lineEdit.installEventFilter( &filter ); lineEdit.show(); return app.exec(); }
Event Propagation
Event propagation is when an event is passed to the base class.
Post/Send Events
- Qt applications rarely need to call postEvent() or sendEvent() directly because most events are generated automatically by Qt or by the window system
- Most of the times Qt includes a function that does it for you. For example, update() and repaint().
Custom Events
- Qt lets you create your own event types
- Custom types can be useful in single-threaded applications, as an inter-object communication mechanism
- A custom event can be handled by an object. To make a custom event you have to:
- Implement this class's custom event handler (customEvent(…)), so that when an event is sent to an instance of this class, this method will be called to handle the situation.
- Send an event using QApplication::postEvent(…) and give an instance of the class mentioned before as one of the parameters.