我的 Qt eventFilter() 不会停止事件,因为它应该

新手上路,请多包涵

我的 eventFilter 存在根本问题,因为它允许 每个 事件通过,而我想停止 一切。我已经阅读了很多关于 QEventeventFilter() 等等的文档,但显然我错过了一些重要的东西。本质上,我正在尝试为基于 QDialog 的弹出窗口类创建自己的模式功能。我想实现我自己的,因为内置的 setModal(true) 包含很多我想排除的功能,例如播放 QApplication::Beep()基本上,我想丢弃所有进入创建我的 popup 的 QWidget (窗口)的事件。到目前为止,我所拥有的是,

 // popupdialog.h
#ifndef POPUPDIALOG_H
#define POPUPDIALOG_H

#include <QDialog>
#include <QString>

namespace Ui {class PopupDialog;}

class PopupDialog : public QDialog
{
   Q_OBJECT
public:
    explicit PopupDialog(QWidget *window=0, QString messageText="");
    ~PopupDialog();
private:
    Ui::PopupDialog *ui;
    QString messageText;
    QWidget window; // the window that caused/created the popup
    void mouseReleaseEvent(QMouseEvent*); // popup closes when clicked on
    bool eventFilter(QObject *, QEvent*);
};

 // popupdialog.cpp
#include "popupdialog.h"
#include "ui_popupdialog.h"

PopupDialog::PopupDialog(QWidget *window, QString messageText) :
    QDialog(NULL), // parentless
    ui(new Ui::PopupDialog),
    messageText(messageText),
    window(window)
{
    ui->setupUi(this);
    setAttribute(Qt::WA_DeleteOnClose, true); // Prevents memory leak
    setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    ui->message_text_display->setText(messageText);

    window->installEventFilter(this);

    //this->installEventFilter(window); // tried this also, just to be sure ..
}

PopupDialog::~PopupDialog()
{
    window->removeEventFilter(this);
    delete ui;
}

// popup closes when clicked on
void PopupDialog::mouseReleaseEvent(QMouseEvent *e)
{
    close();
}

这就是问题所在,过滤器不起作用。请注意,如果我在 --- 中写了一个 std::cout if(...) ,我看到它会在将事件发送到 window 时触发,它只是不会停止它们。

 bool PopupDialog::eventFilter(QObject *obj, QEvent *e)
{
    if( obj == window )
        return true; //should discard the signal (?)
    else
        return false; // I tried setting this to 'true' also without success
}

当用户与主程序交互时,可以像这样创建一个 PopupDialog:

 PopupDialog *popup_msg = new PopupDialog(ptr_to_source_window, "some text message");
popup_msg->show();
// I understand that naming the source 'window' might be a little confusing.
// I apologise for that. The source can in fact be any 'QWidget'.

其他一切都按预期工作。只有事件过滤器失败。 我希望过滤器删除发送到创建弹出窗口的窗口的事件;就像鼠标点击和按键一样,直到弹出窗口关闭。当有人在我的代码中指出一个微不足道的修复时,我预计会非常尴尬。

原文由 Wololo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 521
2 个回答

您必须忽略到达 window 的小部件树中的所有事件。因此,您需要在应用程序范围内安装 eventFilter 并检查您要过滤的对象是否是 window 的后代。换句话说:替换

window->installEventFilter(this);

经过

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

并以这种方式实现事件过滤器功能:

 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;
}

我试过了,测试了它,它对我有用。

注意: 根据我的经验,在 Qt 中使用事件过滤器有点混乱,因为发生的事情并不是很透明。预计错误会不时出现。如果您和您的客户因此对灰显的主窗口没有问题,您可以考虑禁用主窗口。

原文由 Ralph Tandetzky 发布,翻译遵循 CC BY-SA 3.0 许可协议

请参阅此代码以过滤掉特定事件:-

 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);
    }
}

如果您想在多个小部件上设置更具体的事件过滤器,您可以参考以下代码:

  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);

原文由 Shamkumar Rajput 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题