我的 Qt eventFilter() 不会停止事件,因为它应该 [英] My Qt eventFilter() doesn't stop events as it should

查看:22
本文介绍了我的 Qt eventFilter() 不会停止事件,因为它应该的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Something is fundamentally wrong with my eventFilter, as it lets every single event through, while I want to stop everything. I've read lots of documentation on QEvent, eventFilter() and so on, but obviously I'm missing something big. Essentially, I'm trying to create my own modal-functionality for my popup-window class based on QDialog. I want to implement my own since the built-in setModal(true) includes a lot of features, e.g. playing QApplication::Beep(), that I want to exclude. Basically, I want to discard all events going to the QWidget (window) that created my popup. What I have so far is,

// 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::coutif(...) 中,我看到它确实会在将事件发送到 window 时触发,它只是不会停止它们.

Here's the problem, the filter doesn't work. Note that if I write a std::cout inside the if(...), I see that it does trigger whenever events are sent to window, it just doesn't stop them.

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:

When the user interacts with the main program, a PopupDialog can be created like this:

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'.

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

Everything else works as expected. Only the event filter fails. I want the filter to remove events sent to the window that created the popup; like mouse clicking and key pressing, until the popup is closed. I'm expecting to be extremely embarrassed when someone points out a trivial fix in my code.

推荐答案

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

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

通过

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.

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

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.

这篇关于我的 Qt eventFilter() 不会停止事件,因为它应该的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆