Download as pdf or txt
Download as pdf or txt
You are on page 1of 31

 LearnQt Guides (https://www.learnqt.

guide) NAV

WORKING WITH QT
EVENTS
Working With Qt Events : A
Comprehensive Guide
All you need to know about working with events in Qt.

Qt has two main mechanisms to allow developers to react to things that happen in your applica-
tion. One of these, which is more common is Signals and Slots. The other one, is using events. The
aim of this guide is to lay out a comprehensive coverage of different techniques to deliver and
handle events in Qt applications. The guide is highly practical and provides enough ground for
the reader to try out the techniques in the IDE right way. It is expected of the reader to already
have a basic understanding on working with Qt.

Content
1. What Are Events
2. Events and Signals/Slots
3. Using Events
4. Event Propagation
5. A Concrete Example
6. Events and Event Classes
7. Different Methods to Handle Events in Qt
8. Reimplementing QObject::event()
9. Event Filters on QObject
10. Installing Event Filter on QApplication
11. Subclassing QApplication and implementing notify()
12. Sending your own events
13. Summary
What are Events
Events are objects in your Qt C++ application, and they are indeed represented by the QEvent
class. For example there is an event for when someone clicks on a button : QMouseEvent, an
event for when one of your widgets is resized QResizeEvent, an event for when your application
is closed QCloseEvent and so on.

They are a low level mechanism allowing you to control the look and the behavior of your classes
and objects, especially widgets. They are very useful for building event related features inside
your objects, that you do not want to depend on other objects in the application. For example, if I
want my button to turn green when the mouse is hovering on top of it, you can use events to do
that, and that behavior is not going to depend on any other object used with our button.

Events can either be generated from within the application or as a result of some external activ-
ity. When an event occurs, Qt constructs an appropriate instance of a QEvent subclass . Qt deliv-
ers the event by calling the event() method of the target object ( mostly widgets) . The event()
method doesn’t handle the event itself. It looks at the type of the event in question (
Event::Type), and calls the most appropriate event handler ( mousePressEvent,
mouseMoveEvent, keyPressEvent,…) and returns true or false, based on whether the event was
accepted or ignored. I know some of the things are not clear by now, but bare with me, we’re go-
ing to explain more as we move forward and by the end of the guide, most of this stuff is going to
make sense.

Events and Signals/Slots


The purpose of events is somewhat the same as for signals and slots. Signals /Slots allow you to
respond when something happens after all. Hre is how it works. Something happens, a signal is
emitted, and if interested in that signal, you connect it to your slot and respond however you
want in the implementation of your slot.

Events are different in that they allow you to do much more low level things that deeply affect
the behavior of your objects. And if you look deep, the signal and slot mechanism in Qt is itself
powered by events. That’s right ! The clicked() signal of QPushButton for example, is emitted
somewhere deep in the implementation of some mouse events for the QPushButton class.The
most popular use for events I am personally familiar with is when building completely custom
widgets , or deeply customizing existing ones.
Using Events
There are different ways you can use events in you Qt applications. We’re going to start off by
showing you how you can play around with events for the QWidget class. From there, we’re go-
ing to explore more ways you can use events in your Qt applications. Start off by creating a
Widgets application in Qt Creator, I prefer to use QWidget as my parent class, but
QMainWindow will also work just �ne. You should start off with your widget header class look-
ing something like below

class Widget : public QWidget


{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};

If you wanted to capture the close event for the widget, you would add an override of the
closeEvent() method to your widget as shown below

class Widget : public QWidget


{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
protected:
void closeEvent(QCloseEvent * event);
private:
Ui::Widget *ui;
};

and implement it in the implementation �le as shown below


void Widget::closeEvent(QCloseEvent *event)
{
event->accept();
qDebug() << "QCloseEvent : Widget closed";
}

And just like this, we have handled the close event ourselves in our Widget class. If you run the
application, you’ll going to see your usual boring widget. But if you click on the X icon in the top
bar to close the window, you’ll see that your widget closes but you’re going to see a debug mes-
sage saing “QCloseEvent : Widget closed”, proving that our event handler is indeed being called
when the widget is closed.

This is the normal �ow you’re going to follow to implement your events,

• Subclass your Qt class of interest


• Override the event you are interested in

How to know the event you’ll override ? I hear you ask. Well you have to check the Qt documen-
tation for your class of interest. For example we can �nd closeEvent, mousePressEvent,
mouseReleaseEvent and many more in the QWidget class documentation.

Before we go off and start exploring many of the other events you can play with on the QWidget
class, let’s talk about the event->accept() line we have in our event implementation. When you
handle an event like we just did, you have the option to ACCEPT the event, or to IGNORE the
event. When you accept the event, by calling the accept() method on your event parameter,
you’re signaling to the Qt framework that you have dealt with the event and it won’t try to han-
dle it in any other way.

When you ignore the event by calling ignore() on your event parameter, you’re telling the Qt
framework that you’re rejecting the event, and it will try to �nd other ways to handle the event if
possible. In our example we have accepted the event and all is working as expected : the widget
is closing when we click on the X icon. You should also know that if you don’t explicitly specify
that you accept the event like below

void Widget::closeEvent(QCloseEvent *event)


{
qDebug() << "QCloseEvent : Widget closed";
}

the event is going to be accepted by default. That’s a key piece of information to keep in mind.
Before we try that, I want to challenge you to think about what is going to happen if we ignore
the event in our event handler. You ignore the event by calling ignore() on your event.

void Widget::closeEvent(QCloseEvent *event)


{
event->ignore();
qDebug() << "QCloseEvent : Widget closed";
}

Try this and run the application. The widget is going to show up and if you click on the X icon to
close the widget, NOTHING is going to happen! You’re just going to see the debug output from
the event handler but Qt is just going to ignore the event in this case. If you happen to need to
disable the X(Close) icon on your widgets, this is one way you can achieve this.

Event Propagation
The behavior we just saw for the closeEvent, where calling ignore() on the event parameter
causes the widget closing operation to be canceled is special. In normal cases, Qt will try to prop-
agate the event up the parent child relationship chain until it �nds a handler willing to deal with
the event. If that handler is not found, then the event is discarded or fully ignored. A good typical
example is the keyPressEvent() handler, that responds to keyboard key presses. Quoting the
documentation

» This event handler, for event event, can be re implemented in a subclass to receive key
press events for the widget. A widget must call setFocusPolicy() to accept focus initially
and have focus in order to receive a key press event. If you re implement this handler, it is
very important that you call the base class implementation if you do not act upon the
key. The default implementation closes popup widgets if the user presses the key
sequence for QKeySequence::Cancel (typically the Escape key). Otherwise the event is
ignored, so that the widget’s parent can interpret it. Note that QKeyEvent starts with

«
isAccepted() == true, so you do not need to call QKeyEvent::accept() – just do not call
the base class implementation if you act upon the key.. (Qt Documentation)

To handle keyPressEvents you have to subclass your class of interest and override the
keyPressEvent() method. This is starting to become second nature by now.

Another key piece of information speci�c to this event, is that the widget for which you are han-
dling the event, must currently be holding the focus. You can give focus to a widget by clicking in-
side, for example widgets like QLineEdit and QTextEdit, but you can also do that programatically
on a Widget by calling its setFocus() method. This is an example of a behavior tied to a speci�c
event, and it reinforces the good practice of always checking what the of�cial documentation
has to say about a given event you might be interested in handling.

The quoted line in the doc also says that

» The default implementation closes popup widgets if the user presses the key sequence

«
for QKeySequence::Cancel (typically the Escape key). Otherwise the event is ignored, so
that the widget’s parent can interpret it. . (Qt Documentation)

It makes it clear that the parent implementation of keyPressEvent is doing some stuff.
Depending on what you are trying to achieve, you may or may not be interested in what the par-
ent implementation has to offer. If you want to completely bypass what the parent implementa-
tion is doing, just do your thing in your overridden event handler and don’t call the parent imple-
mentation. By the way, you call the parent implementation by doing something like this

QWidget::keyPressEvent(event);

By passing in your event parameter, if your parent class happens to be QWidget for example.
This is what is meant by event propagation. Events can be , and in most cases are , propagated
from parent to child until an object is found, that is interested in the event. Child classes propa-
gate to parents by calling the same event method in their parent classes.

Another pillar of event propagation is knowing when and how to use the accept() and ignore()
methods of the event you are passing around. If an object or widget detects that an event has
been handled by somebody before, it doesn’t bother handling it. The methods are just conve-
niences on top of the setAccepted() method of the event object, which sets the accepted �ag. In
most cases, you won’t need to call accept() explicitly because the event is sent to you in your
event handler with that �ag set to true by default.

A Concrete Example
We have seen quite a lot about events so far, so it’s a good time to �re off our Qt Creator IDE and
play with these events a little more. Open the IDE up and create a new Widgets project. Add a
new class and call it MyLineEdit . The class is going to inherit QLineEdit, because we want to cap-
ture keyPressEvents as we type text in the LineEdit. Modify the header of your class to look like
below
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit MyLineEdit(QWidget *parent = nullptr);
void keyPressEvent(QKeyEvent *event);
};

and the implementation CPP �le to look like below

MyLineEdit::MyLineEdit(QWidget *parent) : QLineEdit(parent)


{
}

void MyLineEdit::keyPressEvent(QKeyEvent *event)


{
qDebug() << "MyLineEdit : keyPressEvent , key : " << event->text();
QLineEdit::keyPressEvent(event);
}

You can go on and create an instance of this class in your widget class to see it, but we’re going to
resist the temptation now. Instead, create a new class and name it ChildLineEdit, modify its
header to look like below

#include "mylineedit.h"
class ChildLineEdit : public MyLineEdit
{
Q_OBJECT
public:
explicit ChildLineEdit(QWidget *parent = nullptr);
void keyPressEvent(QKeyEvent *event);

};

and its implementation CPP �le to look like below


ChildLineEdit::ChildLineEdit(QWidget *parent) : MyLineEdit(parent)
{
}

void ChildLineEdit::keyPressEvent(QKeyEvent *event)


{
qDebug() << " ChildLineEdit,keyPressEvent , key : " << event->text();
MyLineEdit::keyPressEvent(event);
}

This class is inheriting the MyLineEdit class we created earlier, so we need to include the “myli-
needit.h” header �le as seen in our header �le above. Now you can jump into your widget class
constructor and create an instance of ChildLineEdit as shown below

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);

//Declare child Line Edit


ChildLineEdit * childLineEdit = new ChildLineEdit(this);
QVBoxLayout * layout = new QVBoxLayout(this);
layout->addWidget(childLineEdit);

setLayout(layout);
}

We are creating an instance of our ChildLineEdit and assigning the current widget as the parent.
Next we’re putting it in the layout of the widget. If you run the application, it’s going to look
something like below

Type something in the LineEdit and you’re going to see that both the event handlers in
ChildLineEdit and MyLineEdit are called. Can you thing of a reason why ? This is event propaga-
tion in action. ChildWidget is handling keyPressEvent doing something in that event handler : we
are just printing a debug statement in this case but you could have just as easily done anything
you want in there. After our custom thing, we are calling the parent implementation of
keyPressEvent.

MyLineEdit::keyPressEvent(event);
by passing in our event as the parameter. This causes the event handler from MyLineEdit to be
called and we see its output in the screenshot shown above. To play around a little bit, modify
ChildLineEdit::keyPressEvent() as shown below

void ChildLineEdit::keyPressEvent(QKeyEvent *event)


{
qDebug() << " ChildLineEdit,keyPressEvent , key : " << event->text();
qDebug() << "Event accepted : " << event->isAccepted();
MyLineEdit::keyPressEvent(event);
}

On line number 4, we print out the accepted �ag of the event to see if it’s accepted ( true ) or ig-
nored( false) by default. Run the application, type something in the LineEdit, and you’re going to
see that it’s true by default.

This means that the event parameter gets to you in the event handler as if somebody had al-
ready called the accept() method on it. So if you just want to do your thing in there and �ag the
event as accepted, you can omit the call to accept(). But it’s good practice to just put it in there
for code readability reasons. In the parent( MyLineEdit) implementation , we can investigate the
accepted �ag the event gets there with but modifying the event handler as shown below

void MyLineEdit::keyPressEvent(QKeyEvent *event)


{
qDebug() << "MyLineEdit : keyPressEvent , key : " << event->text();
if( event->isAccepted()){
qDebug() << "Event has been already handled";
}else{
qDebug() << "Event hasn't been handled yet";
}
QLineEdit::keyPressEvent(event);
}

Run the application, the output should look something like

ChildLineEdit,keyPressEvent , key : "d"


Event accepted : true
MyLineEdit : keyPressEvent , key : "d"
Event has been already handled

As can be seen, the event is �agged as already handled. This causes parent handlers not to take
any action on the given event. You can go back in ChildLineEdit and explicitly ignore the event as
shown below

void ChildLineEdit::keyPressEvent(QKeyEvent *event)


{
qDebug() << " ChildLineEdit,keyPressEvent , key : " << event->text();
qDebug() << "Event accepted : " << event->isAccepted();
event->ignore();
MyLineEdit::keyPressEvent(event);
}

Run the app, and the output will look like

ChildLineEdit,keyPressEvent , key : "d"


Event accepted : true
MyLineEdit : keyPressEvent , key : "d"
Event hasn't been handled yet

meaning that the event is �agged as ignored in the ChildLineEdit, which is re�ected in the
MyLineEdit. If you want to stop the event from propagating up the chain all together, you can
omit the call to the parent implementation. If you comment out the call to
MyLineEdit::keyPressEvent(event), you’ll see that only ChildLineEdit::keyPressEvent is going to
be called.

void ChildLineEdit::keyPressEvent(QKeyEvent *event)


{
qDebug() << " ChildLineEdit,keyPressEvent , key : " << event->text();
qDebug() << "Event accepted : " << event->isAccepted();
event->ignore();
//MyLineEdit::keyPressEvent(event);
}

But notice the problem here. When you type something in the line edit, you don’t see the text in-
side. This is because we have not called the MyLineEdit::keyPressEvent() , which in turn called
QLineEdit::keyPressEvent(). It turns out QLineEdit::keyPressEvent() contains the implemetation
code for making that text show up . This shows that calling the parent implementation in your
event handlers can be crucial for your application to work the way you want it.
Events and Event Classes
So far, we have touched on only a bunch of events for you to grab a few concepts �rst, but you
should know that there is a whole world of them out there for you to play with. Events are all
subclasses of the QEvent class and each child class adds new �elds and methods to help ful�ll
the purpose it was made for. For example the QResizeEvent will contain the old size and the cur-
rent size for the widget, the QMouseEvent will contain the location where the mouse was
clicked on the screen and so forth. Below is a widget subclass with a few more events for you to
play with. The header is as shown below

class Widget : public QWidget


{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
protected:
void closeEvent(QCloseEvent * event);
void contextMenuEvent(QContextMenuEvent * event);
void enterEvent(QEvent * event);
void leaveEvent(QEvent * event);
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
void mouseDoubleClickEvent(QMouseEvent * event);
void mouseMoveEvent( QMouseEvent * event );
void keyPressEvent( QKeyEvent * event );
void wheelEvent( QWheelEvent * event );
void resizeEvent(QResizeEvent * event);
void paintEvent(QPaintEvent * event);
private:
Ui::Widget *ui;
};

and here is the implementation cpp �le for it


Widget::~Widget()
{
delete ui;
}

void Widget::closeEvent(QCloseEvent *event)


{
// event->accept();
// event->ignore();
qDebug() << "QCloseEvent : Widget closed";
}

void Widget::contextMenuEvent(QContextMenuEvent *event)


{
qDebug() << "ContextMenu";
event->accept();
qDebug() << "QContextMenuEvent : Should pop up a context menu";
qDebug() << "Event x :" << event->x() << " event y : " <<event->y();
qDebug() << "Event reason : " << event->reason();

event->ignore();
}

void Widget::enterEvent(QEvent *event)


{
event->accept();
qDebug() << "Mouse pointer entered widget space";
}

void Widget::leaveEvent(QEvent *event)


{
event->accept();
qDebug() << "Mouse pointer left widget space";
releaseKeyboard();
}

void Widget::mousePressEvent(QMouseEvent *event)


{
qDebug() << "Mouse pressed";
qDebug() << "Button : " << event->button();
grabKeyboard();
event->accept();
}

void Widget::mouseReleaseEvent(QMouseEvent *event)


{
qDebug() << "Mouse released";
releaseKeyboard();
event->accept();
}

void Widget::mouseDoubleClickEvent(QMouseEvent *event)


{
qDebug() << "Mouse double clicked";
event->accept();
}

void Widget::mouseMoveEvent(QMouseEvent *event)


{
qDebug() << "Mouse moved to ("<<event->x() << "," << event->y() << ")";
event->accept();
}

void Widget::keyPressEvent(QKeyEvent *event)


{
qDebug() << "KeyPress event, pressed the key" << event->key();
QString modifiers;
if ( event->modifiers()&amp;Qt::ShiftModifier){
modifiers += "Shift ";
}
if ( event->modifiers()&amp;Qt::ControlModifier){
modifiers += "Control ";
}
if ( event->modifiers()&amp;Qt::AltModifier){
modifiers += "Alt ";
}
qDebug() << "Modifiers : " << modifiers;

//Detect Shift+A
if ( event->modifiers() &amp; Qt::ShiftModifier){
if(event->key() == 65){//
qDebug() << "Shift A detected";
}
}
}

void Widget::wheelEvent(QWheelEvent *event)


{

qDebug() << "Weel Event Delta : " << event->delta();


qDebug() << " x : " << event->x() << ", y : " <<event->y();
qDebug() << " Orientation : " << event->orientation();

void Widget::resizeEvent(QResizeEvent *event)


{

qDebug() << "Widget resized , old size : " << event->oldSize();


qDebug() << " new size : " << event->size();
}

void Widget::paintEvent(QPaintEvent *event)


{
//Can be triggered for multiple reasons. Examples are when widget is resized or w
qDebug() << "Paint event. Rect is : " << event->rect();

The implementation �le my contain things we haven’t talked about yet, but they are speci�c to
given events and you can check the of�cial documentation for more details on these. I just
wanted to give you more examples using other events we haven’t talked about.

NOTE : Don’t just look at these events. Fire off the IDE and play with them.

Different Methods to Handle Events in Qt


So far, we have only seen one way to handle events in Qt : subclassing your class of interest and
overriding event methods. This is the most common way but also the least powerful way to do
the job. In this section, you’re going to get the whole picture when it comes to handling events.
Quoting the documentation,there are �ve different ways that events can be processed; reimple-
menting this virtual function is just one of them. All �ve approaches are listed below:
1. Reimplementing paintEvent(), mousePressEvent() and so on. This is the most common,
easiest, and least powerful way.
2. Reimplementing QCoreApplication::notify. This is very powerful, providing complete control;
but only one subclass can be active at a time.
3. Installing an event �lter on QCoreApplication::instance(). Such an event �lter is able to
process all events for all widgets, so it’s just as powerful as reimplementing notify();
furthermore, it’s possible to have more than one application-global event �lter. Global event
�lters even see mouse events for disabled widgets. Note that application event �lters are only
called for objects that live in the main thread.
4. Reimplementing QObject::event() (as QWidget does). If you do this you get Tab key presses,
and you get to see the events before any widget-speci�c event �lters.
5. Installing an event �lter on the object. Such an event �lter gets all the events, including Tab
and Shift+Tab key press events, as long as they do not change the focus widget.

We have seen number 1 so far so we won’t talk any more about it.

Reimplementing QObject::event()
You use this method by subclassing your class of interest but instead of implementing speci�c
event handlers like keyPressEvent() …, you implement the QObject::event() override. This allows
all events to pass through your override and you can decide which ones to handle and which
ones to channel up the event propagation chain. To play with this, let’s create a QPushButton
subclass and implement our own event() override as shown in the header below

class MyButton : public QPushButton


{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
signals:
protected:
bool event(QEvent * event) override;
public slots:
};

The implementation cpp �le looks like


MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{
}

bool MyButton::event(QEvent *event)


{
if( (event->type() == QEvent::MouseButtonPress)
|| (event->type() == QEvent::MouseButtonDblClick)){
qDebug() << "MyButton::Event : Pressed the MyButton instance. Consuming event
return true;
}
//Remember to call the event method of the base class for the events that you don
return QPushButton::event(event);
}

You may have noticed that the event() method returns bool . The logic here is very similar to
what we’ve seen with the accept() and ignore() methods. When you return true, you are telling
the Qt system that the event has been handled and a returned false means that the event has
been ignored.

Because all events are passing through this method, you have to check which speci�c event you
received. You do that by relying on the Event::Type enum . From the code above, you see that we
are detecting mouse clicks and double clicks for our custom button. If it’s either of these events,
we show a debug output statement and return true to signal that the event has been handled.
Please note that you have to call the parent implementation of event() for all events that you
don’t handle. Otherwise you’re going to end up with an unresponsive widget for other events.

This method is good if for some reason you want to channel all your events through one place.
Also as stated in the documentation , you get Tab key presses, and you get to see the events be-
fore any widget-speci�c event �lters.

To try this out, create an instance of the button in your widget class and connect a slot to it

MyButton * myButton = new MyButton(this);


myButton->setText("MyButton");
connect(myButton,SIGNAL(clicked()),this,SLOT(myButtonClicked()));

Run the application and you’re going to see that as you click or double click on the button, the
slot is not going to be called. Instead, the message from MyButton::event() is going to show up
MyButton::Event : Pressed the MyButton instance. Consuming event

Now why isn’t the slot connected to the button not being called? It is because the the signal con-
nected to that slot : clicked() , isn’t being �red. The signal is �red somewhere in the event handles
of QPushButton, and we have bypassed any event handling for QPushButton whatsoever when
we detect that the user is just clicking (QEvent::MouseButtonPress) or double clicking
(QEvent::MouseButtonDblClick) on our button. This also shows that the event() method is called
before any speci�c event handler like mousePress or keyPress is called.

Event Filters on QObject


Event �lters are subclasses of the QObject class that you can attach to a given object to inter-
cept events before they reach the target object. For example you can attach a �lter to a button
and the �lter will get mouse press events before the button does. You install the �lter by calling
QObject::installEventFilter() on the object. An event �lter gets to process events before the tar-
get object does, allowing it to inspect and discard the events as required. An existing event �lter
can be removed using the QObject::removeEventFilter() function. You intercept events in the
eventFilter() method that you have to override. As an example, let’s suppose that we want to �l-
ter out numbers when somebody is typing in a line edit. We could create a DigitFilter class as
shown below

class DigitFilter : public QObject


{
Q_OBJECT
public:
explicit DigitFilter(QObject *parent = nullptr,QString msg = "");
protected:
bool eventFilter( QObject *dest, QEvent *event );

signals:

public slots:
private :
QString message;
};

The implementation could be something like


DigitFilter::DigitFilter(QObject *parent,QString msg) : QObject(parent)
{
message = msg;
}

bool DigitFilter::eventFilter(QObject *dest, QEvent *event)


{
if( event->type() == QEvent::KeyPress )
{
qDebug() << "Event filter for " << message << " triggered";
QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
static QString digits = QString("1234567890");
if( digits.indexOf( keyEvent->text() ) != -1 )
//Returning true here signals that the event has been handled and it's no
return true;
}
//This sends the event to be handled by the filter of the base class or the event
return QObject::eventFilter(dest, event);
}

The event �lter is also going to get all events for the object it is installed on. Once inside the
eventFilter() method, we have to check for the event we are interested in. In this case, KeyPress
events. After that, we have to check which key was pressed, to know whether it is a digit or not.
If it is we return true to signal that we don’t want this event handled any further, in other words,
the event �lter has done all that needs be done for this event on the target object ( where it is in-
stalled), Nobody else up the chain of event propagation should worry about it. This causes for
digits not to be shown or processed when you type them on the line edit where we’re going to in-
stall the �lter. Assuming you have a bare bones widget project created and opened in Qt Creator,
add the DigitFilter class to the project, and drag a line edit component to the widget form. In the
wiget constructor, create a �lter and install it on the line edit as shown below

DigitFilter* filter = new DigitFilter(this," line edit");


ui->lineEdit->installEventFilter(filter);
ui->lineEdit->setText("line edit");

This will cause for all events for the line edit to go through the eventFilter() method of the �lter
object. The �lter will �lter out digits and you won’t see then in the user interface when you run
the application. Run the app and try this out! Event �lters are great when you don’t want to mess
with the target object and just want to in�uence it’s behavior though events.
Installing Event Filter on QApplication
Besides installing �lters on regular QObjects, you can also install them on the single
QApplication instance in your application. Obviously , event �lters on QApplication are called
before any event �lter installed on any other object in the application. Let’s try this out.
Assuming you have a bare bones widget application created in the IDE, create a new �lter class
and call it MFilter

class MFilter : public QObject


{
Q_OBJECT
public:
explicit MFilter(QString message,QObject *parent = nullptr);
protected:
bool eventFilter( QObject *dest, QEvent *event );
signals:
public slots:
private:
QString m_message;
};

It’s just a regular �lter like we’ve seen before. Its implementation is as shown below

MFilter::MFilter(QString message,QObject *parent) : QObject(parent),


m_message(message)
{
}

bool MFilter::eventFilter(QObject *dest, QEvent *event)


{
if( event->type() == QEvent::MouseButtonPress
|| event->type() == QEvent::MouseButtonDblClick){
qDebug() << "Event hijacked " << m_message;
return true; //Event handled here. No need to propagate
}
return QObject::eventFilter(dest,event);
}

I hope it’s clear that we’re �ltering for mouse clicks and double clicks. Now you can full scale in
craziness, and install this �lter on the QApplication instance in your main function
int main(int argc, char *argv[])
{
QApplication a(argc, argv);

Widget w;

MFilter * filter = new MFilter("FromMain",&amp;w);


a.installEventFilter(filter);
w.show();

return a.exec();
}

If you create buttons in your form and attach slots to respond when they are clicked like below

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);

MFilter * filter = new MFilter("FromWidget",this);


ui->button1->installEventFilter(filter);

Widget::~Widget()
{
delete ui;
}

void Widget::on_button1_clicked()
{
qDebug() << "Clicked on button1";
}

void Widget::on_button2_clicked()
{
qDebug() << "Clicked on button2";
}
and run the application, you’re going to see that when you click on the buttons, the slots are not
going to respond, instead you’re going to see the �lter respond in the debug output message be-
low

Event hijacked "FromMain"

Subclassing QApplication and


implementing notify()
QApplication::notify() is the method that is called by Qt to send the event to the receiver. Using a
subclass of QApplication in your Qt app and overriding the virtual method notify() is by far the
most powerful method to intercept events and handle them. The way you use it is strikingly simi-
lar to what we’ve seen with QObject::event() and QObject::eventFilter. You subclass
QApplication

class Application : public QApplication


{
Q_OBJECT
public:
explicit Application(int &amp;argc, char **argv);
protected:
bool notify(QObject *receiver, QEvent *event);
signals:
public slots:
};

and override the notify() method as shown below


Application::Application(int &amp;argc, char **argv) : QApplication(argc,argv)
{
}

bool Application::notify(QObject *receiver, QEvent *event)


{
Q_UNUSED(receiver);
if ( event->type() == QEvent::MouseButtonPress
|| event->type() == QEvent::MouseButtonDblClick){
qDebug() << "Notify method of Application called";
return true;
}
return QApplication::notify(receiver,event);
}

Again, where we’re just �ltering out mouse clicks and double clicks. You use this subclass of
QApplication where you would use a regular QApplication class.

int main(int argc, char *argv[])


{
Application a(argc, argv);
Widget w;
w.show();
return a.exec();
}

To try this out, you could create buttons in your widget app , connect signals from buttons to
slots and debug output something in the slots. If you run the app, the slots are not going to re-
spond on button clicks because clicks and double clicks are �ltered out in our Application::no-
tify() override.

From what we’ve seen so far, you can hopefully grasp how �exible Qt is in terms of event han-
dling. To me personnaly, it feels like a �owing river, giving you different exit points where you can
pass through to do your own thing.

With all thee options however, the question arises of which method one should use in their ap-
plication. My strategy in everything, is to start from low caliber weapons and only upgrade to
heavier ones when necessary. What I usually do is just inherit the class of interest and speci�c
event handlers. I also use �lters a lot especially when I have one crafted out that I can use on
many widgets or objects. But this is my personal experience. I’m sure that, as you use more and
more of Qt GUI, you’re going to develop your own habits when it comes to using events.

Sending your own events


The �ve methods to handle events we just looked at are what you will mostly choose from when
responding to events in your Qt Apps. However, in the documentation, you will most of the time
come across the postEvent() and sendEvent() methods, that are used to send your own events to
target objects in your Qt application. So we’re going to explore them a bit for completeness.

The documentation for sendEvent is pretty clear, it just sends the event to the target immedi-
ately. postEvent() works slightly in a different way in that it adds the event to some de�ned
queue, and all events in the queue are processed later at a time that is decided by Qt. Each has
its bene�ts and its drawbacks. Please note that you will rarely need to call these methods di-
rectly as, for one, there aren’t many opportunities for you as a developer to generate events that
you would want to send somewhere, events are mostly going to be generated by the user of your
app ( clicks,…) or the window system. The second reason is that even if you need to generate
events, you will usually do that through Qt de�ned methods like update() and repaint() . In case
you’re curious , we’re going to try and send our own event.

Create a regular bare bones widget application. Add a new QPushButton subclass for which
you’re going to override mousePressEvent, mouseMoveEvent and mouseReleaseEvent. The
header is shown below

class Button : public QPushButton


{
Q_OBJECT
public:
explicit Button(QWidget *parent = nullptr);
protected:
void mouseMoveEvent(QMouseEvent * e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
signals:
public slots:
};

and the implementation below


Button::Button(QWidget *parent) : QPushButton(parent)
{
}

void Button::mouseMoveEvent(QMouseEvent *e)


{
qDebug() << "Mouse move at " << e->pos() ;
QPushButton::mouseMoveEvent(e);
}

void Button::mousePressEvent(QMouseEvent *e)


{
qDebug() << "Mouse press at " << e->pos() ;
QPushButton::mousePressEvent(e);
}

void Button::mouseReleaseEvent(QMouseEvent *e)


{
qDebug() << "Mouse release at " << e->pos() ;
QPushButton::mouseReleaseEvent(e);
}

Our intent is to create two buttons in our user interface, button1 and button2. In button1’s slot,
we’re going to craft a MouseEvent and send it to button2. In other words, when you click on but-
ton1, it’s going to look like you’re clicking on button2.

For us to see these events, button2 should be an instance of our custom Button class. A portion
of our widget class looks like below
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);

button2 = new Button(this);


button2->setText("I am the phoenix king");
}

Widget::~Widget()
{
delete ui;
}

void Widget::on_button1_clicked()
{
QMouseEvent * mEvt = new QMouseEvent(QEvent::MouseButtonRelease, QPointF(10,10),
if(QApplication::sendEvent(button2, mEvt)){
qDebug() << "Event accepted";
}else{
qDebug() <<"Event rejected";
}
}

button1 is de�ned in the ui form but its connected slot can be seen above. Inside it we are
crafting a mouse event and giving it all the relevant information like which mouse button and the
location of the click, and we send it to the target using the static QApplication::sendEvent()
method. Because this method returns a bool indicating whether the event was accepted ( true )
or ignored ( false) , we leverage that return value to debug output that information.

button2 is going to receive the event and its relevant event handlers are going to be triggered. If
you run the app and click on button1, you’re going see that button2 is going to respond through
its event handlers.

Mouse release at QPoint(10,10)


Event accepted

You can change the event to QEvent::MouseButtonPress or QEvent::MouseMove to trigger the


other event handlers. Using postEvent() to queue events is just as easy.
void Widget::on_button1_clicked()
{
QMouseEvent * mEvt = new QMouseEvent(QEvent::MouseButtonRelease, QPointF(10,10),
QApplication::postEvent(button3,mEvt);
}

Running the app produces the same effect as sendEvent.

Summary
Working with the event system is a critical skill for any Qt C++ GUI developer. This guide walked
you through what events are, how they compare to signals and slots, how to use events. We
went ahead and to look at some of most interesting events you can handle in your widget class
and what is meant by event propagation. In later sections we explored different ways the Qt
Event System offers work with events doing the best possible to give you concrete examples to
play with the concepts right away. The article wraps up showing you how you can use
sendEvent() and postEvent() to send your own events to objects. If you have any question, sug-
gestion or just want to kick off a chat about the Event System of Qt, don’t hesitate to ping me in
the comments below. I hope this was informative to you guys and thanks for reading.

 Daniel Gakwaya (https://rutura.github.io/daniel.gakwaya/)  2019-04-12 


EVENTS
 Qt  Events

« Qt 5.12 LTS is out .Time to update your projects. (https://www.learnqt.guide/qt-5-12-lts-


is-out-time-to-update-your-projects)

Archive (https://www.learnqt.guide/blog/archive/)

Why host both on Udemy and LearnQt » (https://www.learnqt.guide/why-learnqt-udemy/)

Dialogue & Discussion


3 Comments 
1 Login

Join the discussion…

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name

Sort by Best  ⥅

Jim Hankins • 9 months ago


Would be great if you had an example of subclassing QEvent and handling with
customEvent.
△ ▽ • Reply • Share ›

Valdomiro Morais • a year ago


Thanks, Daniel!
△ ▽ • Reply • Share ›

CapjSparro • 2 years ago


Can we use QEvents in C++ backend of a QtQuick application and use them on the QML
side of it?
△ ▽ • Reply • Share ›

✉ Subscribe 🔒 Privacy ⚠ Do Not Sell My Data

High Quality Online Courses on Qt,C++, Qt Quick/QML and More.


(/courses) See our Courses on Qt,C++ and QML (/courses)

33 Tips and Tricks to Speed up your work�ow .Get this higly visual, 15 pages PDF Guide
On Qt Creator for FREE! GET IT NOW! (https://mailchi.mp/a7c4442d916d/qt-creator-
shortcuts)
(https://mailchi.mp/a7c4442d916d/qt-creator-shortcuts)

Get This Amazing Book for FREE (https://mailchi.mp/a7c4442d916d


/qt-creator-shortcuts)

ABOUT THIS SITE


»LearnQtGuide« creates up to date Qt Learning Video and text format tutorials. More › (https://www.learnqt.guide
/about/)

SERVICES
(https://www.learnqt.guide)
Qt Video Trainings (https://www.learnqt.guide/courses/)

IMPORTANT LINKS
(https://www.learnqt.guide)
Courses on Offer (https://www.learnqt.guide/courses/)
Why do we host courses both on LearnQtGuide and Udemy ? (https://www.learnqt.guide/why-learnqt-udemy/)

© 2022 LEARNQTGUIDES (HTTPS://WWW.LEARNQT.GUIDE/)


(http://github.com
/blikoon)
  
(https://www.youtube.com
(https://twitter.com
(https://web.facebook.com
/channel
/learnqtguide)
/learnqtguide/)
/UCUYUFiuJ5XZ3JYtbq5dXRKQ)

You might also like