My Qt eventFilter() doesn't stop events as it should

两盒软妹~` 提交于 2019-12-05 05:30:50

You have to ignore all events that arrive in the widget tree of the window. Therefore, you need to install the eventFilter application-wide and check, if the object you are filtering on is a descendant of window. In other words: Replace

window->installEventFilter(this);

by

QCoreApplication::instance()->installEventFilter(this);

and implement the event filter function this way:

bool PopupDialog::eventFilter(QObject *obj, QEvent *e)
{
    if ( !dynamic_cast<QInputEvent*>( event ) )
        return false;

    while ( obj != NULL )
    {
        if( obj == window )
            return true;
        obj = obj->parent();
    }
    return false;
}

I tried it, tested it and it worked for me.

Note: Using event filters in Qt is a bit messy in my experience, since it is not quite transparent what is happening. Expect bugs to pop up from time to time. You may consider disabling the main window instead, if you and your clients don't have a problem with the grayed-out main window as a consequence.

After the massive amount of responses, feedback, suggestions and time ivested in extensive research I've finally found what I believe to be the optimal, and safest solution. I wish to express my sincere gratidtude to everyone for their aid to what Kuba Ober describes as "(...) not as simple of a problem as you think".

We want to filter out all certain events from a widget, including its children. This is difficult, because events may be caught in the childrens default eventfilters and responded to, before they are caught and filtered by the the parent's custom filter for which the programmer implements. The following code solves this problem by installing the filter on all children upon their creation. This example assumes the use of Qt Creator UI-forms and is based on the following blog post: How to install eventfilters for all children.

// The widget class (based on QMainWindow, but could be anything) for
// which you want to install the event filter on, includings its children

class WidgetClassToBeFiltered : public QMainWindow
{
    Q_OBJECT
public:
    explicit WidgetClassToBeFiltered(QWidget *parent = 0);
    ~WidgetClassToBeFiltered();
private:
    bool eventFilter(QObject*, QEvent*);
    Ui::WidgetClassToBeFiltered *ui;
};

...

WidgetClassToBeFiltered::WidgetClassToBeFiltered(QWidget *parent) :
    QMainWindow(parent), // Base Class constructor
    ui(new Ui::WidgetClassToBeFiltered)
{
    installEventFilter(this); // install filter BEFORE setupUI.
    ui->setupUi(this);
}

...

bool WidgetClassToBeFiltered::eventFilter(QObject *obj, QEvent* e)

{    
    if( e->type() == QEvent::ChildAdded ) // install eventfilter on children
    {
        QChildEvent *ce = static_cast<QChildEvent*>(e);
        ce->child()->installEventFilter(this);
    }
    else if( e->type() == QEvent::ChildRemoved ) // remove eventfilter from children
    {
        QChildEvent *ce = static_cast<QChildEvent*>(e);
        ce->child()->removeEventFilter(this);
    }
    else if( (e->type() == QEvent::MouseButtonRelease) ) // e.g. filter out Mouse Buttons Relases
    {

       // do whatever ..
       return true; // filter these events out
    }

    return QWidget::eventFilter( obj, e ); // apply default filter
}

Note that this works, because the eventfilter installs itself on added children! Hence, it should also work without the use of UI-forms.

Refer this code to filter out specific event:-

class MainWindow : public QMainWindow
{
public:
    MainWindow();

protected:
    bool eventFilter(QObject *obj, QEvent *ev);

private:
    QTextEdit *textEdit;
};

MainWindow::MainWindow()
{
    textEdit = new QTextEdit;
    setCentralWidget(textEdit);

    textEdit->installEventFilter(this);
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == textEdit) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            qDebug() << "Ate key press" << keyEvent->key();
            return true;
        } else {
            return false;
        }
    } else {
        // pass the event on to the parent class
        return QMainWindow::eventFilter(obj, event);
    }
}

If you want to set more specific event filter on multiple widgets you can refer following code:

 class KeyPressEater : public QObject
 {
     Q_OBJECT

 protected:
     bool eventFilter(QObject *obj, QEvent *event);
 };

 bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
 {
     if (event->type() == QEvent::KeyPress) {
         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
         qDebug("Ate key press %d", keyEvent->key());
         return true;
     } else {
         // standard event processing
         return QObject::eventFilter(obj, event);
     }
 }


 KeyPressEater *keyPressEater = new KeyPressEater(this);
 QPushButton *pushButton = new QPushButton(this);
 pushButton->installEventFilter(keyPressEater);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!