Qt:让父母决定孩子是不是接受事件

Posted

技术标签:

【中文标题】Qt:让父母决定孩子是不是接受事件【英文标题】:Qt: Have parent decide whether or not a child accepts eventQt:让父母决定孩子是否接受事件 【发布时间】:2016-08-04 20:28:06 【问题描述】:

我在尝试让父对象过滤子事件时遇到问题。

在以下示例中,我在旋转框上设置了一个事件过滤器。事件过滤器检测旋转框上的鼠标按下事件。然后,我希望父对象根据某些标准接受或忽略该事件。

问题是它似乎接受了鼠标按下事件,然后忽略了鼠标释放事件。这是鼠标滚轮事件的问题。

我怎样才能让我的父母接受/忽略该事件?

在实际情况下,消息必须通过更多层,但行为是相同的。如果您单击旋转框上的向上箭头,则会弹出消息,然后数字将开始旋转。

Qt 版本:5.6.1

#include "mainwindow.h"

#include <QEvent>
#include <QSpinBox>
#include <QHBoxLayout>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)

    QSpinBox* spinner = new QSpinBox;
    QHBoxLayout* layout = new QHBoxLayout;
    QWidget* widget = new QWidget;
    layout->addWidget(spinner);
    spinner->installEventFilter(this);
    connect(this, SIGNAL(mouse_pressed(QEvent*)),
            this, SLOT(handle_event(QEvent*)));
    widget->setLayout(layout);
    setCentralWidget(widget);


MainWindow::~MainWindow()




bool MainWindow::eventFilter(QObject *watched, QEvent *event)

    if (event->type() == QEvent::MouseButtonPress
        event->type() == QEvent::Wheel)
    
        emit mouse_pressed(event);
    
    return QMainWindow::eventFilter(watched, event);


void MainWindow::handle_event(QEvent* event)

    event->ignore();
    QMessageBox(QMessageBox::Warning, "warning", "ignoring event").exec();    

编辑 1:我找到了一种方法来部分停止事件级联。在 MainWindow::handle_event(...) 中,我调用 'event->setAccepted(false)',而不是调用 'event->ignore()',然后在 eventFilter 中检查 'event->isAccepted()' .如果不被接受,我会忽略该事件。

此解决方案在 QLineEdit 上运行良好,但在 QSpinBox 和 QPushbutton 上仍无法正常运行。对于 QSpinBox,滚轮事件仍会更改值,单击旋转按钮会导致持续旋转(未检测到鼠标释放)。对于 QPushButton,该事件被忽略,但按钮保持按下状态。

编辑 2: 忽略事件后返回 false 会阻止级联。谢谢@GM提示!我会发布一个答案。

【问题讨论】:

Qt 根据return value from eventFilter 决定是否进一步处理事件,但您永远不会从自己的实现中明确返回truefalse。您还声明“问题是它似乎接受了鼠标按下事件,然后忽略了鼠标释放事件”,但您没有显示任何处理鼠标释放事件的代码。 我在eventFilter中返回继承对象函数的结果。 MouseButtonRelease 事件不会保留其默认行为吗?我在 QPushButtons 上看到了同样的问题(他们一直很沮丧)。即使我处理 MouseButtonRelease 事件并调用 btn->setDown(false)。 【参考方案1】:

让父母决定孩子是否应该处理事件的方法是调用“event->setAccepted(false)”,检查eventFilter函数中的。如果为 false,则忽略该事件并从函数中返回 true。

从 eventFilter 函数返回 true 对我来说是违反直觉的,但它就在文档中。事件过滤器的侵入性比子类化小得多,所以我很高兴找到解决方案。

#include "mainwindow.h"

#include <QEvent>
#include <QSpinBox>
#include <QHBoxLayout>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)

    QSpinBox* spinner = new QSpinBox;
    QHBoxLayout* layout = new QHBoxLayout;
    QWidget* widget = new QWidget;
    layout->addWidget(spinner);
    spinner->installEventFilter(this);
    connect(this, SIGNAL(mouse_pressed(QEvent*)),
            this, SLOT(handle_event(QEvent*)));
    widget->setLayout(layout);
    setCentralWidget(widget);


MainWindow::~MainWindow()




bool MainWindow::eventFilter(QObject *watched, QEvent *event)

    if (event->type() == QEvent::MouseButtonPress
        event->type() == QEvent::Wheel)
    
        emit mouse_pressed(event);
        if (!event->isAccepted())
        
            event->ignore();
            return true;
        
    
    return QMainWindow::eventFilter(watched, event);


void MainWindow::handle_event(QEvent* event)

    event->setAccepted(false);
    QMessageBox(QMessageBox::Warning, "warning", "ignoring event").exec();    

【讨论】:

以上是关于Qt:让父母决定孩子是不是接受事件的主要内容,如果未能解决你的问题,请参考以下文章

将悬停样式应用于任何孩子但不是父母

如何为父母声明孩子是Qt中的共享指针

Jquery选择孩子但不是父母

很多孩子问父母

Qt:获取父母区域内的所有孩子

NLP智慧父母 | 我在孩子身上看见了什么?