簡體   English   中英

我的Qt eventFilter()不停止事件,它應該

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

我的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();
}

這就是問題,過濾器不起作用。 請注意,如果我在if(...)內編寫了一個std::cout ,我看到它確實會在事件發送到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'.

其他所有工作均按預期進行。 僅事件過濾器失敗。 我希望過濾器刪除發送到創建彈出窗口的事件。 如鼠標單擊和按鍵,直到關閉彈出窗口 當有人指出我的代碼中的一個小錯誤時,我期望我會感到非常尷尬。

你必須忽略的是,在的widget樹到達所有事件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中使用事件過濾器有點混亂,因為所發生的事情並不十分透明。 期望錯誤會不時彈出。 如果您和您的客戶因此對灰顯的主窗口沒有問題,則可以考慮禁用主窗口。

經過大量研究的大量反饋,反饋,建議和時間,我終於找到了我認為是最佳,最安全的解決方案。 我希望對每個人表示衷心的感謝,感謝他們對庫巴·奧伯所說的“(...)並不像您想的那么簡單”。

我們想從小部件中過濾掉所有某些事件, 包括其子級 這很困難,因為事件可能在子級默認事件過濾器中捕獲並響應, 然后才被程序員實現的父級自定義過濾器捕獲並過濾。 以下代碼通過在所有子項創建時將過濾器安裝在所有子項上來解決此問題。 本示例假定使用Qt Creator UI表單,並且基於以下博客文章: 如何為所有子項安裝eventfilters

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

請注意 ,這是可行的,因為eventfilter會在添加的子代上自行安裝! 因此,它也應該在不使用UI表單的情況下工作。

請參考以下代碼以過濾特定事件:-

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM