Skip to content
nucularmoo edited this page Mar 20, 2018 · 16 revisions

Object Communicating: Event Handlers

Explanation of the contents of a topic page @ Week 1 Topic 1

Back to Week 1

Objective: Customising event handling

Comment: Attendees should learn like in the next section that event Signals/Slots is the preferred way. Sometimes it's wiser to re-implement event handling, if for example we need custom behaviour for some type, but we do not need to notify anyone about this. For example, we would like to visually show that there was a touch event. This would be trivial to implement to QWindow, which receives all GUI events rather than trying to solve this with Signals/Slots.

E: Could this be called "The Event System"? It's the topic of http://doc.qt.io/qt-5/eventsandfilters.html and consistency comes to mind

Beginner

  • What are Events?

Intermediate

  • What are Event Handlers?
  • How to customise event handling/event handlers?
  • How to re-implement any event function?
  • When to use Signals/Slots and when to use event handlers?

Expert


Course material content

http://doc.qt.io/qt-5/events.html

Communication between Qt and the Application is handled trough the events [SLIDES]

  1. generate events

Spontaneous events Asynchronous, e.g. mouse, touch or key press events Generated by the underlying window system Read and queued by a QPA plug-in Processed by the event loop

Synthetic events Created in Qt program Synchronous or asynchronous

  1. Queue events

Spontaneous and asynchronous synthetic events queued by the event loop

QCoreApplication::exec()runs the main event loop

The event loop tells the event dispatcher what to do and how to do it For example: wait for an event, exclude user input events

  1. Dispatch events

Platform-specific event dispatchers derived from QAbstractEventDispatcher

Event dispatcher receives events from the window system and other sources via the event loop Delivers events to QCoreApplication

Events and Event Handlers

http://doc.qt.io/qt-5/eventsandfilters.html#event-handlers

Generate Events By input devices: keyboard, mouse, etc. By Qt itself (e.g. timers) Queue Events By event loop Dispatch Events By QApplication to receiver: QObject Key events sent to widget/Qt Quick item with focus Mouse events sent to widget/Qt Quick item under cursor Handle Events By QObject event handler methods [SLIDES]

In Qt, events are objects, derived from the abstract QEvent class, that represent things that have happened either within an application or as a result of outside activity that the application needs to know about. Events can be received and handled by any instance of a QObject subclass, but they are especially relevant to widgets. This document describes how events are delivered and handled in a typical application.

When an event occurs, Qt creates an event object to represent it by constructing an instance of the appropriate QEvent subclass, and delivers it to a particular instance of QObject (or one of its subclasses) by calling its event() function.

This function does not handle the event itself; based on the type of event delivered, it calls an event handler for that specific type of event, and sends a response based on whether the event was accepted or ignored.

Some events, such as QMouseEvent and QKeyEvent, come from the window system; some, such as QTimerEvent, come from other sources; some come from the application itself.

Event Types

Most event types have special classes, notably QResizeEvent, QPaintEvent, QMouseEvent, QKeyEvent, and QCloseEvent. Each class subclasses QEvent and adds event-specific functions. For example, QResizeEvent adds size() and oldSize() to enable widgets to discover how their dimensions have been changed.

Some classes support more than one actual event type. QMouseEvent supports mouse button presses, double-clicks, moves, and other related operations.

Each event has an associated type, defined in QEvent::Type, and this can be used as a convenient source of run-time type information to quickly determine which subclass a given event object was constructed from.

Since programs need to react in varied and complex ways, Qt's event delivery mechanisms are flexible. The documentation for QCoreApplication::notify() concisely tells the whole story; the Qt Quarterly article Another Look at Events rehashes it less concisely. Here we will explain enough for 95% of applications.

Event Handlers

The normal way for an event to be delivered is by calling a virtual function. For example, QPaintEvent is delivered by calling 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, the following code handles left mouse button clicks on a custom checkbox widget while passing all other button clicks to the base QCheckBox class:

 void MyCheckBox::mousePressEvent(QMouseEvent *event)
 {
      if (event->button() == Qt::LeftButton) {
           // handle left mouse button here
      } else {
           // pass on other buttons to base class
           QCheckBox::mousePressEvent(event);
      }
 }

If you want to replace the base class's function, you must implement everything yourself. However, if you only want to extend the base class's functionality, then you implement what you want and call the base class to obtain the default behavior for any cases you do not want to handle.

Occasionally, there isn't such an event-specific function, or the event-specific function isn't sufficient. The most common example involves Tab key presses. Normally, QWidget intercepts these to move the keyboard focus, but a few widgets need the Tab key for themselves.

These objects can reimplement QObject::event(), the general event handler, and either do their event handling before or after the usual handling, or they can replace the function completely. A very unusual widget that both interprets Tab and has an application-specific custom event might contain the following event() function:

 bool MyWidget::event(QEvent *event)
 {
      if (event->type() == QEvent::KeyPress) {
           QKeyEvent *ke = static_cast<QKeyEvent *>(event);
           if (ke->key() == Qt::Key_Tab) {
                // special tab handling here
                return true;
           }
      } else if (event->type() == MyCustomEventType) {
           MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);
           // custom event handling here
           return true;
      }

      return QWidget::event(event);
 }

Note that QWidget::event() is still called for all of the cases not handled, and that the return value indicates whether an event was dealt with; a true value prevents the event from being sent on to other objects.

Customising event handlers

Re-implementing event functions

Sometimes it's wiser to re-implement event handling, if for example we need custom behaviour for some type, but we do not need to notify anyone about this. For example, we would like to visually show that there was a touch event.

Choosing between Signals/Slots and Event Handlers

Attendees should learn like in the next section that event Signals/Slots is the preferred way.


Exhaustive reference material mentioned in this topic

Further reading topics/links:

Clone this wiki locally