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:

    second.cpp

    #include "second.h"
    #include <QtWidgets>
    
    second::second(QWidget *parent) : QWidget(parent)
    {
        qApp->installEventFilter(parent);
    }
    
    second::~second(){
    
    }
    
    bool second::eventFilter(QObject *watched, QEvent *event){
        //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:

    #include "first.h"
    #include "second.h"
    
    first::first(QWidget *parent) : QMainWindow(parent)
    {
        second *tempSecond = new second(this);
    }
    
    first::~first()
    {
    
    }
    
    bool first::eventFilter(QObject *watched, QEvent *event){
        //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?


  • Moderators

    @Oleg21 This cannot work this way.
    Please read http://doc.qt.io/qt-5/qobject.html#installEventFilter
    The event filter you install in second is only for second instances!
    Furthermore the object you set as event filter has to implement eventFilter method else it is not a filter - that's why first has to implement eventFilter in your example. If you need an eventFilter at the top level then you need to install an event filter object in the top level widget.
    From design point of view it is bad if some subwidget installs a top level event filter.


  • Qt Champions 2016

    Hi
    Not sure its the best way but worked for my use case.
    I installed the eventfilter on the application and return false to let it
    give to any other event filter installed. ( like for comboboxes)

    IN ITS OWN FILE, NOT PART OF MAIN !
    (i inlined it to be easier to show)
    #include <QObject>
    #include <QMouseEvent>
    #include <QDebug>
    #include <QCursor>
    
    class myEventFilter: public QObject {
      Q_OBJECT
    public:
      myEventFilter() {}
      ~myEventFilter() {
      }
    protected:
      bool eventFilter(QObject* object, QEvent* event) {
        if(event->type() == QEvent::MouseMove) {
          int x = QCursor::pos().x();
          int y = QCursor::pos().y();
          qDebug() << "MP -> (" + QString::number(x) + "," + QString::number(y) + ")";
          return false; // make it unhandled and sent to other filters.
        } else
          return false;
      }
    };
    
    ---
    then in main.cpp
    
    #include "filterclass.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        a.installEventFilter(new myEventFilter()); // this can be controlled by a flag.
        MainWindow w;
        w.show();
        return a.exec();
    }
    
    


  • @jsulm Hi, thank you for your advice. I have already thought of abandoning my idea. That is, implement all code in the class first. However, mrjj, offered a very interesting solution for me, I have to try it.



  • @mrjj Hi, thank you for the idea, I did not guess about such implementation of the code. I will definitely try this.



  • @mrjj Hi, so really, your decision helped me. Thanks!



  • @mrjj Hi, I wanted to ask: do you had the effect of double-running eventFilter?
    That is, I create a global variable and in eventFilter I increment it. I output the result in qDebug. But I see that the variable does not increase by one unit, but increases by two units.


  • Qt Champions 2016

    @Oleg21

    Hmm. Only one time where i did install it multiple times.
    You just did like
    int cc=0;

    --

    and in eventfilter
    cc++; ?

    Note that doc says:
    "If multiple event filters are installed on a single object, the filter that was installed last is activated first."



  • @mrjj So I found my mistake! I did not listen to you and now I have a negative result. Here's the problem:

    • You wrote that you should install event filter in application. As shown in code main.cpp:
    #include "first.h"
    #include <QApplication>
    #include "second.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        first w;
        
        w.installEventFilter(new second());
        
        w.show();
    
        return a.exec();
    }
    
    • But, I decided I could install the event filter in the second.cpp class constructor:
    second::second(QWidget *parent) : QWidget(parent)
    {
        qApp->installEventFilter(this);
    }
    

    This was the cause of incorrect behavior. I'm sorry.

    But still, maybe you know why this is happening?


  • Qt Champions 2016

    Hi
    You seems to install 2 filters.
    w.installEventFilter(new second());
    w is first class. not application. Not sure what that expression does as
    a constructor cannot return anything.

    qApp->installEventFilter(this); // one on app.

    if you want second to handle the filter for application, you can just do do
    w.installEventFilter(new second());
    second local;

    But its a bit odd as you dont use instance and its nothing more than just
    qApp->installEventFilter(this); // to get just one

    So what/why you want second class? if i may ask.
    You plan it offers other service than eventfilter?



  • @mrjj Hi, of course I will answer. All this interests me because I want to implement the code in a separate class. This separate class, I want to include to different projects, not thinking about implementation of the code.

    Simply put, all things related to eventFilter are placed in a separate class. And then include it where you need it without completing any more code.

    However, this is no longer important. By your example, I will be able to come up with something. Thanks again for the advice.


  • Qt Champions 2016

    @Oleg21
    Ok i understand. a utility class. That's not a bad idea.
    I have something the same where i included all events names so it can provide better info
    when using a filter. ( for spying ;)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.