Professional Documents
Culture Documents
Working With QT Events A Comprehensive Guide
Working With QT Events A Comprehensive Guide
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 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
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
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,
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
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.
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 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);
};
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);
};
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);
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
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
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
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.
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
event->ignore();
}
//Detect Shift+A
if ( event->modifiers() & Qt::ShiftModifier){
if(event->key() == 65){//
qDebug() << "Shift A detected";
}
}
}
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.
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
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
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.
signals:
public slots:
private :
QString message;
};
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
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
It’s just a regular �lter like we’ve seen before. Its implementation is as shown below
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;
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);
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
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.
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.
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
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);
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.
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.
Archive (https://www.learnqt.guide/blog/archive/)
LOG IN WITH
OR SIGN UP WITH DISQUS ?
Name
Sort by Best ⥅
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)
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/)
(http://github.com
/blikoon)
(https://www.youtube.com
(https://twitter.com
(https://web.facebook.com
/channel
/learnqtguide)
/learnqtguide/)
/UCUYUFiuJ5XZ3JYtbq5dXRKQ)