1
votes

I want to add an event to an object. Therefore I created a class that implements a eventFilter.

Minimal example:

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <iostream>

#include <QVBoxLayout>

#include "eventwatcher.cpp"
#include "mynewlineedit.cpp"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QVBoxLayout *mainLay = new QVBoxLayout();

    MyNewLineEdit *lineEdit;

    for(int i = 0; i < 3; i++)
    {
        lineEdit = new MyNewLineEdit();
        mainLay->addWidget(lineEdit);
        new EventWatcher(lineEdit);
    }

    QWidget *centWid = new QWidget();
    centWid->setLayout(mainLay);

    setCentralWidget(centWid);
}



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


eventwatcher.cpp:

#include <QWidget>
#include <QDebug>
#include <QKeyEvent>

#include <iostream>

class EventWatcher : public QObject
{
public:
   explicit EventWatcher(QWidget* parent = Q_NULLPTR) : QObject(parent)
   {
       if (parent)
       {
           parent->installEventFilter(this);
       }
   }

   virtual bool eventFilter(QObject*, QEvent* event) Q_DECL_OVERRIDE
   {
       if (event->type() == QEvent::KeyPress)
       {
           std::cout << "Pressed any key\n";
       }

       return false;
   }
};


mynewlineedit.cpp

#include <QLineEdit>
#include <iostream>

class MyNewLineEdit : public QLineEdit
{
public:
    MyNewLineEdit() : QLineEdit()
    {}

protected:
    void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE
    {
        std::cout << "Event of the parent object\n";
    }
};

Add CONFIG += console to the .pro file

The project is a normal Qt-Widgets-Application all other files are not modified.

The result is the following:

Pressed any key

Event of the parent object


The eventFilter it self works fine. But there is a problem with the order of the event handling.

The eventFilter is executed before the KeyPressEvent of the parent object is triggered. But for me, it is important, that the event Filter trigers, after the KeyPressEvent of the parent object.

The result I want to get is the following:

Event of the parent object

Pressed any key

Is there any way to define the order of execution?

1
With that given code I don't think the parent's KeyPressEvent would be triggering at all, does it ?Sumit
Yes I am sure, that the parent's KeyPressEvent triggers. I created a little minimal example. I hope it is easier for you.NelDav
Thanks for sharing the code, return false; in eventFilter() is why now KeyPressEvent () is getting triggered. Reproduced your issue, could not fix yet. If you will write return true; inside if() and after std::cout << "Pressed any key\n"; KeyPressEvent() will not trigger If that does not help what you want, please tell what do you want to achieve by calling the filter later ? I mean its natural to filter out unwanted stuff first then do anything with the cream and thats how its working currently...Sumit
Can below give what you want: void MyNewLineEdit::keyPressEvent(QKeyEvent *event) { std::cerr << "Event of the parent object\n"; A_Method(this,event); //A_Method can be anywhere, consider it like eventFilter }Sumit

1 Answers

1
votes

Here is the solution that I have come-up with:

  • Rename your mynewlineedit.cpp to mynewlineedit.h , change everywhere
  • And change eventwatcher.cpp to this:

#include <QWidget>
#include <QDebug>
#include <QKeyEvent>

#include <iostream>
#include <mynewlineedit.h>
class EventWatcher : public QObject
{
    QWidget* m_parent;
public:
   explicit EventWatcher(QWidget* parent = Q_NULLPTR) : QObject(parent), m_parent(parent)
   {
       if (parent)
       {
           parent->installEventFilter(this);
       }
   }

   virtual bool eventFilter(QObject*, QEvent* event) Q_DECL_OVERRIDE
   {
       if (event->type() == QEvent::KeyPress)
       {
           if(m_parent)
           {
               dynamic_cast<MyNewLineEdit*>(m_parent)->keyPressEvent(dynamic_cast<QKeyEvent*>(event));
           }
           std::cerr << "Pressed any key\n";
           return true;
       }

        return false;
   }
};