QWidget 似乎忽略了 EventFilter 传递的事件

Posted

技术标签:

【中文标题】QWidget 似乎忽略了 EventFilter 传递的事件【英文标题】:QWidget seems to ignore event passed by EventFilter 【发布时间】:2018-06-27 10:00:02 【问题描述】:

我在尝试使用 QT eventFilter 传递事件时遇到问题。

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
if(event->type() == QEvent::Wheel)
    QPoint pos = QCursor::pos();
    QWidget *widget = QApplication::widgetAt(pos);
        if(widget != NULL)
            widget->setVisible(false); //for Test purposes only
            qDebug() << widget; //also for test 
            QApplication::sendEvent(widget, event); //should send event to widget?
                return true;
            

                return true;
        
    return false;

我想捕捉鼠标滚轮的滚动并将其一次传递给多个 QWidget。如果我在没有 sendEvent 的情况下执行上述操作,我想参加的小部件将消失(这就是我想要的测试)。如果我使用 sendEvent,什么都不会发生,或者它会因分段错误错误而崩溃……我尝试了我在网上找到的任何东西(或者我至少是这么认为的)..

提前致谢!!!

【问题讨论】:

如果您将事件发送到小部件,您将最终陷入无限递归,因为事件过滤器会再次拦截它。如果您希望小部件接收事件,只需返回 false,如果您想停止事件传播,请返回 true 【参考方案1】:

当您调用QApplication::sendEvent(widget, event); 并且如果widgetMainWindow 或其自身的孩子,接收事件将在MainWindow::eventFilter 中再次过滤。它创建了一个递归无限循环。 如果事件正在发送,我向return true; 添加了一个标志sendingEvent。希望能有所帮助。

bool MyWindow::eventFilter(QObject *obj, QEvent *event)

    if (event->type() == QEvent::Wheel)
    
        static bool sendingEvent = false;
        if (sendingEvent)
        
            //exit recursive call, return false to avoid swallowing the event
            return false;
        
        QPoint pos = QCursor::pos();
        QWidget *widget = QApplication::widgetAt(pos);
        if (widget != NULL)
            qDebug() << widget; //also for test         

            //set the flag before sending event
            sendingEvent = true;

            QApplication::sendEvent(widget, event); //should send event to widget?

            //reset the flag after sending event
            sendingEvent = false;
            return true;
        
        return true;
    
    return false;

【讨论】:

非常感谢!我已经想知道为什么 qDebug 输出列出了这么多项目。我也猜想这将解决崩溃!但是该事件似乎仍然没有传递给小部件......这是一个 QCustomPlot 应该在滚动时放大。 (当我在事件过滤器中直接返回 false 时它确实有效,因此在小部件站点上处理事件应该不是问题)。 对不起,我返回 true 以退出递归调用,因为它吞下了事件。已更新为 return false; 很高兴听到这个消息!

以上是关于QWidget 似乎忽略了 EventFilter 传递的事件的主要内容,如果未能解决你的问题,请参考以下文章

QTableView 中 Drop-Events 的 EventFilter

忽略 QWidget 点击事件并将其传播到操作系统

(十三)事件分发器——event()函数,事件过滤

accept()函数用来告诉Qt,事件处理函数“接收”了这个事件,不要再传递;ignore()函数则告诉Qt,事件处理函数“忽略”了这个事件,需要继续传递(看一下QWidget::mousePress

QWidget类中默认是忽略inputMethodEvent事件(要获取输入的内容就必须使用这个事件)

无法忽略任务栏菜单中的最大化事件