2016-08-04 81 views
2

我有一個問題,試圖讓父對象過濾兒童事件。Qt:請家長決定是否接受兒童事件

在以下示例中,我在旋轉框上設置了一個事件過濾器。事件過濾器檢測旋轉框上的鼠標按下事件。然後,我會根據一些標準,讓父對象接受或忽略該事件。

問題是,它似乎接受鼠標按下事件,然後忽略鼠標釋放事件。這是鼠標滾輪事件的問題。

我該如何讓父母接受/忽略該事件?

在實際情況下,消息必須通過更多層,但行爲是相同的。如果您單擊旋轉框上的向上箭頭,則會彈出消息,然後數字將開始旋轉。

的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-> ignore()',而是調用'event-> setAccepted(false)',然後檢查eventFilter中的'event-> isAccepted()' 。如果它不被接受,我會忽略這個事件。

該解決方案對QLineEdit運行良好,但仍然無法按預期的方式使用QSpinBox和QPushbutton。對於QSpinBox,輪子事件仍然會更改該值,並單擊旋轉按鈕會導致持續旋轉(未檢測到鼠標釋放)。對於QPushButton,該事件被忽略,但按鈕保持按下狀態。

編輯2:忽略事件後返回錯誤會阻止級聯。謝謝@GM。提示!我會發佈一個答案。

+2

的Qt來決定是否進一步處理基於[返回值從'eventFilter']事件(http://doc.qt.io/qt-5/qobject.html#eventFilter),但你從未明確地從您自己的實現中返回「true」或「false」。您還聲明「問題在於它似乎接受了鼠標按下事件,然後忽略了鼠標釋放事件」,但您沒有顯示處理鼠標釋放事件的任何代碼。 –

+0

我在eventFilter中返回繼承的對象函數的結果。 MouseButtonRelease事件不會保留其默認行爲嗎?我看到與QPushButtons相同的問題(他們保持抑鬱)。即使我處理MouseButtonRelease事件並調用btn-> setDown(false)。 – vincent

回答

0

讓父母決定是否應該處理一個事件的方法是調用'event-> setAccepted(false)',檢查eventFilter函數中的內容。如果它爲假,則忽略該事件並從該函數返回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();  
}