Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to make an eventfilter?

How to make an eventfilter?

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 15.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alexandre Camelo
    wrote on 5 Jan 2020, 13:45 last edited by
    #1

    I need to use events in various controls (line edits, comboboxes, etc.), in addition to the events (slots) already in the menu.

    I've read the eventfilters documentation below:

    https://doc.qt.io/qt-5/eventsandfilters.html

    I tried to do as explained, but I guess I didn't know where to put each of the instructions (and maybe there were other errors of mine).

    I would like to know exactly how to do it.

    @mrjj , can you help me?

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 5 Jan 2020, 14:36 last edited by mrjj 1 May 2020, 14:42
      #2

      Hi
      Luckly its not super complicated.

      Lets try to catch the focusIn/out

      we need to add a event filter function to some object that will handle it for us.
      Often mainwindow is used as the widget we monitor is living there.
      Place a QLineEdit on the form.

      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
      private:
          Ui::MainWindow *ui;
          bool eventFilter(QObject *object, QEvent *event); <<< add this
      };
      

      then in cpp.

      in the Mainwindow constructor, we add.
      ui->lineEdit->installEventFilter(this);

      now we need the body of the filter function

      
      bool MainWindow::eventFilter(QObject *object, QEvent *event)
      {
      
          if ( object == ui->lineEdit &&  ( event->type() == QEvent::HoverEnter )  ) {
              ui->lineEdit->setText("IN");
          }
      
      
          if ( object == ui->lineEdit &&  (event->type() == QEvent::HoverLeave )  ) {
              ui->lineEdit->setText("out");
          }
      
          // false means it should be send to target also. as in , we dont remove it.
          // if you return true , you will take the event and widget never sees it so be carefull with that.
          return false; 
      }
      

      and if we then run it
      alt text

      This is a very powerful way of altering how the std. widgets works but if you use for all cases where subclassing ( like we did in other thread) would be more self-contained, you will discover its hard to understand a program if there are filters all over the place.
      But a filter is very good for one widget to alter something. However if to be used in many place and many forms in the app. Then subclassing is far less messy.

      A 1 Reply Last reply 5 Jan 2020, 15:58
      5
      • M mrjj
        5 Jan 2020, 14:36

        Hi
        Luckly its not super complicated.

        Lets try to catch the focusIn/out

        we need to add a event filter function to some object that will handle it for us.
        Often mainwindow is used as the widget we monitor is living there.
        Place a QLineEdit on the form.

        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            explicit MainWindow(QWidget *parent = nullptr);
            ~MainWindow();
        private:
            Ui::MainWindow *ui;
            bool eventFilter(QObject *object, QEvent *event); <<< add this
        };
        

        then in cpp.

        in the Mainwindow constructor, we add.
        ui->lineEdit->installEventFilter(this);

        now we need the body of the filter function

        
        bool MainWindow::eventFilter(QObject *object, QEvent *event)
        {
        
            if ( object == ui->lineEdit &&  ( event->type() == QEvent::HoverEnter )  ) {
                ui->lineEdit->setText("IN");
            }
        
        
            if ( object == ui->lineEdit &&  (event->type() == QEvent::HoverLeave )  ) {
                ui->lineEdit->setText("out");
            }
        
            // false means it should be send to target also. as in , we dont remove it.
            // if you return true , you will take the event and widget never sees it so be carefull with that.
            return false; 
        }
        

        and if we then run it
        alt text

        This is a very powerful way of altering how the std. widgets works but if you use for all cases where subclassing ( like we did in other thread) would be more self-contained, you will discover its hard to understand a program if there are filters all over the place.
        But a filter is very good for one widget to alter something. However if to be used in many place and many forms in the app. Then subclassing is far less messy.

        A Offline
        A Offline
        Alexandre Camelo
        wrote on 5 Jan 2020, 15:58 last edited by
        #3

        @mrjj said in How to make an eventfilter?:

        This is a very powerful way of altering how the std. widgets works but if you use for all cases where subclassing ( like we did in other thread) would be more self-contained, you will discover its hard to understand a program if there are filters all over the place.
        But a filter is very good for one widget to alter something. However if to be used in many place and many forms in the app. Then subclassing is far less messy.

        It worked!

        One more great and accurate tip, mrjj!

        This is exactly what I was looking for from the beginning.

        With eventfilter, it is much easier to intercept the events of the controls I want and the difficulty is almost nil.

        What's more, it's much faster.

        About comparing eventfilters and subclasses ... I have a question:

        Can I put events from all the controls I want into the same function body as the event filter? Example: Within the same function body, put events of a line edit, a combobox and a text edit. Can i do that?

        If so, I think it is much easier to understand such a program, as I only need to make 1 prototype (in the .h file) and 1 function (in the .cpp file) and throw all the events in this body (I am inexperienced in QT and my program is still in the beginning, so I may be wrong). I'm wrong?

        Thank you so much again.

        M 1 Reply Last reply 5 Jan 2020, 16:17
        0
        • A Alexandre Camelo
          5 Jan 2020, 15:58

          @mrjj said in How to make an eventfilter?:

          This is a very powerful way of altering how the std. widgets works but if you use for all cases where subclassing ( like we did in other thread) would be more self-contained, you will discover its hard to understand a program if there are filters all over the place.
          But a filter is very good for one widget to alter something. However if to be used in many place and many forms in the app. Then subclassing is far less messy.

          It worked!

          One more great and accurate tip, mrjj!

          This is exactly what I was looking for from the beginning.

          With eventfilter, it is much easier to intercept the events of the controls I want and the difficulty is almost nil.

          What's more, it's much faster.

          About comparing eventfilters and subclasses ... I have a question:

          Can I put events from all the controls I want into the same function body as the event filter? Example: Within the same function body, put events of a line edit, a combobox and a text edit. Can i do that?

          If so, I think it is much easier to understand such a program, as I only need to make 1 prototype (in the .h file) and 1 function (in the .cpp file) and throw all the events in this body (I am inexperienced in QT and my program is still in the beginning, so I may be wrong). I'm wrong?

          Thank you so much again.

          M Offline
          M Offline
          mrjj
          Lifetime Qt Champion
          wrote on 5 Jan 2020, 16:17 last edited by mrjj 1 May 2020, 16:18
          #4

          @Alexandre-Camelo
          Hi
          Good it just worked :)

          Yes, you can handle events to any number of widgets in the filter function.
          The function is
          bool eventFilter(QObject *object, QEvent *event);

          and the object is the object (doh) that is about to get the event.

          Since the widget comes as base QObject * you will/might need to use
          qobject_cast to cast it to the actual type so your logic can

          say if its a QLineEdit , do
          if its a ComboBox do

          You will need a line
          ui->XXXX->installEventFilter(this);
          for each widget, you want to control this way.

          The standard way to implement an event function is normally via subclassing.
          And then simply use this class instead of the std. one.

          However, for simple things like focus in/out , event filters can be used.

          Issues with event filters will show as soon as you need to remember something between events for a given class. Then the filter function can become quite complicated and
          a subclass is waaaay better design.

          Also Qt is based on subclassing so event filters are not a replacement for that.

          However, for a simple app with one mainform and no popup dialogs etc then eventfilter will work super fine.

          A 1 Reply Last reply 6 Jan 2020, 11:35
          1
          • M mrjj
            5 Jan 2020, 16:17

            @Alexandre-Camelo
            Hi
            Good it just worked :)

            Yes, you can handle events to any number of widgets in the filter function.
            The function is
            bool eventFilter(QObject *object, QEvent *event);

            and the object is the object (doh) that is about to get the event.

            Since the widget comes as base QObject * you will/might need to use
            qobject_cast to cast it to the actual type so your logic can

            say if its a QLineEdit , do
            if its a ComboBox do

            You will need a line
            ui->XXXX->installEventFilter(this);
            for each widget, you want to control this way.

            The standard way to implement an event function is normally via subclassing.
            And then simply use this class instead of the std. one.

            However, for simple things like focus in/out , event filters can be used.

            Issues with event filters will show as soon as you need to remember something between events for a given class. Then the filter function can become quite complicated and
            a subclass is waaaay better design.

            Also Qt is based on subclassing so event filters are not a replacement for that.

            However, for a simple app with one mainform and no popup dialogs etc then eventfilter will work super fine.

            A Offline
            A Offline
            Alexandre Camelo
            wrote on 6 Jan 2020, 11:35 last edited by
            #5

            @mrjj OK.

            Understood.

            As I plan to do big projects in the future, I will start using subclasses then.

            Thanks again.

            M 1 Reply Last reply 6 Jan 2020, 11:40
            0
            • A Alexandre Camelo
              6 Jan 2020, 11:35

              @mrjj OK.

              Understood.

              As I plan to do big projects in the future, I will start using subclasses then.

              Thanks again.

              M Offline
              M Offline
              mrjj
              Lifetime Qt Champion
              wrote on 6 Jan 2020, 11:40 last edited by
              #6

              @Alexandre-Camelo
              Hi
              Ok deal. :)
              Also as soon as you want to use custom painting, (paintEvent)
              then event filters becomes complicated.

              1 Reply Last reply
              0
              • Z Offline
                Z Offline
                Zonghan Gan
                wrote on 27 Feb 2020, 00:18 last edited by
                #7

                Recently I need to substitute the event type of keypress of a Pong Gui with a self defined event type MyEvent(to Use UDP signal instead <- -> to control the game). However the problem is that seems for self-defined event I need to manually send or post them, while the event filter can't receive the self-defined event (the inbuilt keypress or mouseclick seems need no manually send). The event filter was installed as in mainwindow.cpp: ui->boardView->installEventFilter(gameloop iLoop); the eventfilter is realized in gameplay.cpp:
                '''

                bool Gameplay::eventFilter(QObject *target, QEvent *e)
                {
                Q_UNUSED(target);

                bool handled = false;
                if(e->type() == MyEventType)
                {
                    MyEvent *myevent = (MyEvent *)e;
                    if ( myevent->sg >0)
                    {
                        //pong paddle move left
                        iP1Direction = (iP1Direction == 0 ? -5 : 0);
                        handled = true;
                    }
                    else if ( myevent->sg <0 )
                    {
                        //pong paddle move right
                        iP1Direction  = (iP1Direction == 0 ? 5 : 0);
                        handled = true;
                    }
                }
                if(e->type() == MyEventType)
                {
                    qDebug()<<"abc";
                    handled = true;
                }
                return handled;
                

                }
                '''

                The main.cpp '''

                #include <QtWidgets/QApplication>
                #include "mainwindow.h"
                #include "MyEvent.h"
                #include <iostream>
                #include <cmath>
                int main(int argc, char *argv[])
                {

                QApplication a(argc, argv);
                
                MainWindow w;
                w.show();
                
                
                
                for(int i=0;i<1000;i++){
                MyEvent myEvent1(MyEventType);
                myEvent1.set_ch(1);
                myEvent1.load_sg(1);
                QCoreApplication::postEvent(&w, &myEvent1);
                }
                
                return a.exec();
                

                }
                '''
                the mainwindow.cpp is

                '''
                //cited from https://github.com/ynonp/Pong
                #include <QPen>
                #include <QResizeEvent>
                #include <QDebug>
                #include <QtWidgets/QApplication>
                #include "mainwindow.h"
                #include "MyEvent.h"
                #include <QCoreApplication>
                #include <QEvent>
                #include <QObject>
                #include <QDebug>
                #include <iostream>

                MainWindow::MainWindow(QWidget *parent) :
                QMainWindow(parent),
                ui(new Ui::MainWindow),
                iScore ( 0 )
                {
                ui->setupUi(this);

                QGraphicsScene *scene = new QGraphicsScene(this);
                
                QGraphicsRectItem *p1 = new QGraphicsRectItem(0, 0, 80, 20);
                p1->setBrush(QBrush(Qt::blue));
                QGraphicsRectItem *p2 = new QGraphicsRectItem(0, 0, 80, 20);
                p2->setBrush(QBrush(Qt::green));
                
                QGraphicsEllipseItem *ball = new QGraphicsEllipseItem(0, 0, 15, 15);
                ball->setBrush(QBrush(Qt::magenta));
                
                ui->boardView->setScene(scene);
                
                iLoop = new Gameplay(*scene, p1, p2, ball, this);
                QSize m(scene->sceneRect().size().width() + 10, scene->sceneRect().size().height() + 10);
                ui->boardView->setMinimumSize(m);
                
                resize(minimumSize());
                ui->boardView->installEventFilter(iLoop);
                
                
                QObject::connect(iLoop, SIGNAL(goal(int)),
                                 this, SLOT(addScore(int)));
                

                }

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

                void MainWindow::addScore(int count)
                {
                iScore += count;
                ui->lcdNumber->display(iScore);
                }
                '''

                So how can I feed my self defined event into the GUI event filter?

                Thanks

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved