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:
    1. Register the monitoring object with the target object by calling installEventFilter() on the target.
    2. 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:
    1. 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.
    2. Send an event using QApplication::postEvent(…) and give an instance of the class mentioned before as one of the parameters.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.