eventFilter anywhere in the program.
Hi everyone. The following situation arose: I have a project, it contains two classes (first.cpp and second.cpp).
first.cpp is a constant and compulsory project class, and the second.cpp is an optional class and is connected as needed.
So, in the second.cpp class, I have a desire to implement eventFilter at the program level. For this I write the following code:
Code:
second.cpp
#include "second.h"
#include <QtWidgets>
{
qApp->installEventFilter(parent);
}
second::~second(){
}
//it's not working!
}
Unfortunately, eventFilter in this class does not work.
In order for everything to work, I need to implement eventFilter in class first.cpp:
Code:
#include "first.h"
#include "second.h"
{
second *tempSecond = new second(this);
}
first::~first()
{
}
//it's working!
}
However, this approach contradicts my opinion about the possibility of disabling the class second.cpp.
Tell me, how to solve this problem?
Re: eventFilter anywhere in the program.
Code:
//qApp->installEventFilter(parent);
qApp->installEventFilter(this);
Re: eventFilter anywhere in the program.
Hello. Truly, I had to do as you say:
Code:
qApp->installEventFilter(this);
And implementation of eventFilter:
Code:
if (event
->type
() == QEvent::MouseButtonRelease) {
cc++;
qDebug() << cc;
return false;
}else{
return false;
}
}
However, there is a small problem here: eventFilter function gets MouseButtonRelease event twice.
Should this be so? If so, maybe you know why this happens?
Re: eventFilter anywhere in the program.
Quote:
Originally Posted by
Oleg21
Hello. Truly, I had to do as you say:
However, there is a small problem here: eventFilter function gets MouseButtonRelease event twice.
Should this be so? If so, maybe you know why this happens?
You have installed the event filter on two objects, or may be installed event filer on same object twice.
Re: eventFilter anywhere in the program.
Hmm, weird. I install event filter only in one place of code and only for one object.
Be kind, take a look at the code of my project, and tell me where I was mistaken?
Headers:
first.h
Code:
#ifndef FIRST_H
#define FIRST_H
#include <QMainWindow>
{
Q_OBJECT
public:
~first();
};
#endif // FIRST_H
second.h
Code:
#ifndef SECOND_H
#define SECOND_H
#include <QWidget>
{
Q_OBJECT
public:
explicit second
(QWidget *parent
= nullptr
);
~second();
int cc = 0;
signals:
public slots:
};
#endif // SECOND_H
Sources:
main.cpp
Code:
#include "first.h"
#include <QApplication>
int main(int argc, char *argv[])
{
first w;
w.show();
return a.exec();
}
first.cpp
Code:
#include "first.h"
#include "second.h"
#include <QtWidgets>
{
second *second1 = new second(this);
}
first::~first()
{
}
second.cpp
Code:
#include "second.h"
#include <QtWidgets>
{
qApp->installEventFilter(this);
}
second::~second(){
}
if (event
->type
() == QEvent::MouseButtonRelease) {
cc++;
qDebug() << cc;
return false;
}else{
return false;
}
}
Re: eventFilter anywhere in the program.
print out the address of the 'watched' object, see if both events belong to the same object.
1 Attachment(s)
Re: eventFilter anywhere in the program.
Hello. I already did it. But I have determined that events belong to different objects.
After this code:
Code:
cc++;
qDebug() << cc;
I added the following code:
Code:
qDebug() << watched->metaObject()->className();
Received a result:
Attachment 12611
Therefore, in eventFilter, I added the following kind of verification:
Code:
if (watched->metaObject()->className() == tempStr){
// code here
}
In this case, the issue is resolved. But I do not know if it is correct to do so?
Re: eventFilter anywhere in the program.
Quote:
But I do not know if it is correct to do so?
Depends what your definition of "correct" is.
I would suggest however to not install the event filter on qApp, but on the actual object which of whom you want to filter events, in this case you 'first' object.
This will save you the need to "filter" your objects based on class name which is not optimal (what if you have several objects of the same class?)
1 Attachment(s)
Re: eventFilter anywhere in the program.
Quote:
Originally Posted by
high_flyer
(what if you have several objects of the same class?)
For each object, I can say a unique ObjectName which allows me to know from which object I get the events.
For example:
Code:
first w;
w.setObjectName("Lollipop");
w.show();
In the eventFilter:
Code:
QString tempStr
= "LollipopWindow";
if(watched->objectName() == tempStr){
//Code here
}
}
However, it should be remembered that to the ObjectName is added string "Window". Why this happens, I do not know.
Quote:
Originally Posted by
high_flyer
I would suggest however to not install the event filter on qApp, but on the actual object which of whom you want to filter events, in this case you 'first' object.
The following code:
Code:
qDebug() << watched->metaObject()->className();
returns the following string: "QWidgetWindow", after him "first", after - "second". Why on the "first" should I set the event filter?
Perhaps "QWidgetWindow" is the very first class? And that it should be set to filter events?
But, I do not find a class with that name.
Attachment 12618
What is this class, "QWidgetWindow"? How to find it? Where can I find out about it?
Re: eventFilter anywhere in the program.
Quote:
For each object, I can say a unique ObjectName which allows me to know from which object I get the events.
Sure you *can* do it, but this is hardly good practice, it makes the code very rigid and you are ignoring the fact that when you have the pointer 'watched' it already points to a known (to you) object, so why bother with setting and querying strings when you can simply compare addresses (when you insist to filter on the application level)?
It would more generic, and less rigid and robust to changes you might have later in your code.
I could not understand the text below the qDebug() snippet, sorry.
1 Attachment(s)
Re: eventFilter anywhere in the program.
Quote:
Originally Posted by
high_flyer
I could not understand the text below the qDebug() snippet, sorry.
I apologize for the wrong text. I wanted to say that qDebug () displays the following values:
Attachment 12622
I am interested in the QWidgetWindow value, which is marked in orange.
To which class is this name? Can I install event filter for an object of this class?
Again I apologize for the incomprehensible text.
Re: eventFilter anywhere in the program.
It seems QWidgetWindow is some sort of a non documented helper class, and it derives from QWindow.
Here is a grep output on it (searched only headers):
Code:
./qtbase/src/widgets/kernel/qapplication.h:217: friend class QWidgetWindow;
./qtbase/src/widgets/kernel/qwidget.h:714: friend class QWidgetWindow;
./qtbase/src/widgets/kernel/qwidgetwindow_p.h:40:#ifndef QWIDGETWINDOW_P_H
./qtbase/src/widgets/kernel/qwidgetwindow_p.h:41:#define QWIDGETWINDOW_P_H
./qtbase/src/widgets/kernel/qwidgetwindow_p.h:67:class QWidgetWindow : public QWindow
.
/qtbase
/src
/widgets
/kernel
/qwidgetwindow_p.
h:71: QWidgetWindow
(QWidget *widget
);
./qtbase/src/widgets/kernel/qwidgetwindow_p.h:72: ~QWidgetWindow();
./qtbase/src/widgets/kernel/qwidgetwindow_p.h:139:#endif // QWIDGETWINDOW_P_H
./qtbase/src/corelib/kernel/qcoreapplication.h:220: friend class QWidgetWindow;
Without looking into the code itself, from the grep it seems that this class is a bit like a private implementation class which Qt is heavily using (PIMPL design pattern), probably to inject some special behavior for specific events in specific cases.
I think its safe to assume its your top level application window.
And again, the problem with the QWidgetWindow is a good example why using the string based polling of classes or object names is bad practice and very fragile code.
And because its part of the private Qt area also means it can change, be renames or removed in any future Qt release breaking your code.
3 Attachment(s)
Re: eventFilter anywhere in the program.
Hello. Thank you very much for helping me find "QWidgetWindow".
Quote:
Originally Posted by
high_flyer
And again, the problem with the QWidgetWindow is a good example why using the string based polling of classes or object names is bad practice and very fragile code.
And because its part of the private Qt area also means it can change, be renames or removed in any future Qt release breaking your code.
I absolutely agree with you. Performing a check on the name of the class is not correct.
To better reflect my actions, I threw out unnecessary code from the project.
Consequently, the project contains two classes: first.cpp and second.cpp.
In the first.cpp class, is created an object of the QPushButton class "Button1".
In the second.cpp class, is created an object of the QPushButton class "Button2".
In the second.cpp class is installed events filter for qApp.
In the first.cpp class is created the object of second.cpp "second1".
Graphically I depicted it in the picture below:
Attachment 12625
main.cpp
Code:
#include "first.h"
#include <QApplication>
int main(int argc, char *argv[])
{
first first1;
first1.show();
return a.exec();
}
first.cpp
Code:
#include "first.h"
#include "second.h"
#include <QtWidgets>
{
this->resize(230, 70);
second *second1 = new second(this);
button1->setParent(this);
button1->setText("Button1");
button1->setObjectName("Button1");
button1->setGeometry(120, 10, 100, 25);
}
first::~first()
{
}
second.cpp
Code:
#include "second.h"
#include <QtWidgets>
{
resize(115, 45);
qApp->installEventFilter(this);
button2->setParent(this);
button2->setText("Button2");
button2->setObjectName("Button2");
button2->setGeometry(10, 10, 100, 25);
}
second::~second(){
}
if (event
->type
() == QEvent::MouseButtonRelease) {
cc++;
qDebug() << cc;
qDebug() << watched->metaObject()->className() << endl;
return false;
}else{
return false;
}
}
Now when I'm clicking a mouse on any objects, i have result:
Attachment 12630
Now I installed event filter for "first1" (first.cpp).
Code:
{
resize(115, 45);
parent->installEventFilter(this);
button2->setParent(this);
button2->setText("Button2");
button2->setObjectName("Button2");
button2->setGeometry(10, 10, 100, 25);
}
"parent" is pointer to "first1" object.
When I'm clicking a mouse on "first1" or "second1" i have result:
Attachment 12631
When I'm clicking a mouse on any buttons (button1 or button2) i dont have result. This is probably due to the fact that eventFilter does not work for them.
This is why I want to leave eventFilter for qApp and not for other objects. I want so that eventFilter work globally for all objects.
How to achieve this by setting eventFilter to the first.cpp class object ("first1")?
Re: eventFilter anywhere in the program.
What happens when you do this:
Code:
if (event
->type
() == QEvent::MouseButtonRelease) {
cc++;
qDebug() << cc;
qDebug() << watched->metaObject()->className() << endl;
return false;
}
return QWidget::eventFileter(watched, event
);
}
1 Attachment(s)
Re: eventFilter anywhere in the program.
Quote:
Originally Posted by
high_flyer
What happens when you do this:
When I made the changes as you suggested, nothing has changed:
Code:
if (event
->type
() == QEvent::MouseButtonRelease) {
cc++;
qDebug() << cc;
qDebug() << watched->metaObject()->className() << endl;
return false;
}
/*else{
return false;
}*/
return QWidget::eventFilter(watched, event
);
}
when I'm clicking on "first1" or "second1" i have result:
Attachment 12638
when I'm clicking on any buttons (button1 or button2) i do not have result.
When I made the next code:
Code:
if (event
->type
() == QEvent::MouseButtonRelease) {
cc++;
qDebug() << cc;
qDebug() << watched->metaObject()->className() << endl;
return false;
}
return second::eventFilter(watched, event);
}
then the program is crashed after run.
Re: eventFilter anywhere in the program.
I still don't understand what it is you want to do.
What is the goal you are after? which events do you need form which objects?
If you want to filter the button events, you can install an event filter on the buttons.
This all seems very over engineered and complex for no reason.
Also, do you really need to fileter event by another object?
Are you aware you can process events in the objects themselves by overloading event() or specialized event handler?
In short: please explain what is your goal - not what you want to do (like filtering some event) - depending on the goal we can see what is the best method to achieve it.
Re: eventFilter anywhere in the program.
Quote:
Originally Posted by
high_flyer
I still don't understand what it is you want to do.
What is the goal you are after?
Okay, I want to record actions with the program (with the interface). And save this data in log file.
Quote:
Originally Posted by
high_flyer
which events do you need form which objects?
If you want to filter the button events, you can install an event filter on the buttons.
I want to install global eventFilter, so that work with everyone object at once. I don't want to install unique eventFiletr for all objects in my app. Quantity and type of objects are unknown in advance.
Quote:
Originally Posted by
high_flyer
Also, do you really need to fileter event by another object?
The idea itself is to put this code into a separate class and include it as needed (a utility class).
Quote:
Originally Posted by
high_flyer
Are you aware you can process events in the objects themselves by overloading event() or specialized event handler?
Overloading event() - yes i know about it. But this will force me to overload the event() in all objects. It's complicated.
Therefore, in my opinion, the best option of all is to use:
Code:
qApp->installEventFilter(this);
Re: eventFilter anywhere in the program.
Hello.
You wrote above:
Quote:
Originally Posted by
high_flyer
It seems QWidgetWindow is some sort of a non documented helper class, and it derives from QWindow.
And really it is so! I read the Qt source code. Namely the header file qwidgetwindow_p.h. Here is a warning I saw in this file:
qwidgetwindow_p.h
Code:
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
You were right!
So, on this basis, I firmly decided to refuse to use any parts of the code that mention the "QWidgetWindow" class.
Therefore, I reworked my evenFilter:
Code:
if (event
->type
() == QEvent::MouseButtonPress) {
tempPoint = pe->globalPos();
if (w == watched) {
iTempCount = iTempCount + 1;
qDebug() << iTempCount;
qDebug() << watched->metaObject()->className();
}
return false;
}else{
return false;
}
}
Indeed, this code is also not perfect. But he suits me.
Thank you for the help provided to me. I apologize if I was rude, obtrusive or incomprehensible.