2016-08-04 11 views
2

Ich habe ein Problem beim Versuch, ein übergeordnetes Objekt zu erhalten, um untergeordnete Ereignisse zu filtern.Qt: Lassen Eltern entscheiden, ob ein Kind Ereignis akzeptiert

Im folgenden Beispiel habe ich einen Ereignisfilter auf einem Drehfeld eingerichtet. Der Ereignisfilter erkennt Mausereignisse auf dem Drehfeld. Ich möchte dann, dass das übergeordnete Objekt dieses Ereignis basierend auf einigen Kriterien akzeptiert oder ignoriert.

Das Problem ist, dass es scheint, das Mausereignis zu akzeptieren und dann das Mausereignis zu ignorieren. Dies ist ein Problem mit Mausrad-Ereignissen.

Wie kann ich das Ereignis von meinem Elternteil akzeptieren/ignorieren lassen?

Im realen Fall muss die Nachricht mehr Layer durchlaufen, aber das Verhalten ist das gleiche. Wenn Sie auf den Nach-oben-Pfeil des Drehfelds klicken, wird die Nachricht eingeblendet und die Zahlen beginnen sich zu drehen.

Qt-Version: 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();  
} 

Edit 1: Ich habe einen Weg, um teilweise zu stoppen die Ereigniskaskade gefunden. In MainWindow :: handle_event (...), statt "event-> ignore()" aufzurufen, rufe ich "event-> setAccepted (false)" auf und sucht dann im eventFilter nach "event-> isAccepted()" . Wenn es nicht akzeptiert wird, ignoriere ich das Ereignis.

Diese Lösung hat für QLineEdit funktioniert, aber es funktioniert immer noch nicht wie erwartet mit QSpinBox und QPushbutton. Bei QSpinBox ändert ein Wheel-Ereignis den Wert und durch Klicken auf die Drehfelder wird das Drehen fortgesetzt (keine Mausfreigabe wird erkannt). Für QPushButton wird das Ereignis ignoriert, aber die Schaltfläche bleibt gedrückt.

Bearbeiten 2: Die Rückgabe false nach dem Ignorieren des Ereignisses blockiert die Kaskade. Danke @ G.M. für den Hinweis! Ich werde eine Antwort posten.

+2

Qt entscheidet, ob oder nicht weiter ein Ereignis auf dem [Rückgabewert von 'eventFilter'] (http://doc.qt.io/qt-5/qobject.html#eventFilter), aber sie basiert zu verarbeiten geben Sie niemals 'true' oder' false' von Ihrer eigenen Implementierung zurück. Sie stellen auch fest "Das Problem ist, dass es scheint, das Mausereignis zu akzeptieren und dann das Mausereignis zu ignorieren", aber Sie zeigen keinen Code an, der Mauserreignisse verarbeitet. –

+0

Ich gebe das Ergebnis der geerbten Objektfunktion in eventFilter zurück. Wird ein MouseButtonRelease-Ereignis nicht sein Standardverhalten beibehalten? Ich sehe das gleiche Problem mit QPushButtons (sie bleiben gedrückt). Selbst wenn ich ein MouseButtonRelease-Ereignis verarbeite und btn-> setDown (false) aufruft. – vincent

Antwort

0

Der Weg, den Eltern zu entscheiden, ob ein Kind mit einem Ereignis umgehen soll oder nicht, war der Aufruf von 'event-> setAccepted (false)', der in der eventFilter-Funktion überprüft wird. Wenn es falsch ist, ignoriere das Ereignis und true von der Funktion zurück.

Rückgabe True von der EventFilter-Funktion war für mich nicht eingängig, aber es ist genau dort in der Dokumentation. Ereignisfilter sind weniger invasiv als Unterklassen, daher war ich froh, zu einer Lösung zu kommen.

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