Lodorot
24th June 2009, 15:12
Hi,
I've implemented a sub class of QGraphicsView (MyGraphicsView). I want to install an event filter on this view which handles all "user events". But I've got some trouble with the event handling in Qt.
I thought the propagation order is always:
installed filter -> QObject::event()-> event-specific function (like paintEvent)
I've experienced that this is only true for some events like e.g. QPaintEvent and QKeyEvent in case of QMouseEvent or QWheelEvent the propagation order is:
event-specific function -> installed filter -> QObject::event().
So if I would like to filter QMouseEvents or QWheelEvents for my sub class of QGraphicsView I have to reimplement the event-specific functions (e.g. mouseMoveEvent) there I have to ignore() the event so that the installed filter receives the event. If not doing so the event filter doesn't receive these events.
To me this looks a bit strange. The Qt 4.5 Documentation says : "An event filter gets to process events BEFORE the target object does ..."
Is this a bug a feature or is there something wrong with my code?
I've attached a code snippet and the result for QPaintEvent, QMouseEvent, QKeyEvent and QWheelEvent.
Thank you in advance
Markus
PS: I'm using Qt 4.5.1.
#include "filterevents.h"
filterEvents::filterEvents(QWidget *parent)
: QWidget(parent)
{
// set up from with my graphics view
view = new MyGraphicsView();
layout = new QHBoxLayout();
layout->addWidget(view);
setLayout(layout);
// install event filter
view->installEventFilter(this);
}
bool filterEvents::eventFilter (QObject * object, QEvent * event)
{
if(event->type() == QEvent::KeyPress ||
event->type() == QEvent::Wheel ||
event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::Paint)
qDebug() << event << "in filter.";
return QObject::eventFilter(object, event);
}
#include "MyGraphicsView.h"
#include <QDebug>
MyGraphicsView::MyGraphicsView() {
setMouseTracking(true);
}
MyGraphicsView::~MyGraphicsView() {
}
bool MyGraphicsView::event(QEvent * event) {
if(event->type() == QEvent::KeyPress ||
event->type() == QEvent::Wheel ||
event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::Paint)
qDebug() << event << "in my graphics view (event).";
return QGraphicsView::event(event);
}
void MyGraphicsView::paintEvent(QPaintEvent * event) {
qDebug() << event << "in my graphics view (paintEvent).";
event->ignore();
}
void MyGraphicsView::wheelEvent(QWheelEvent * event) {
qDebug() << event << "in my graphics view (wheelEvent).";
event->ignore();
}
void MyGraphicsView::keyPressEvent(QKeyEvent * event) {
qDebug() << event << "in my graphics view (keyPressEvent).";
event->ignore();
}
void MyGraphicsView::mousePressEvent(QMouseEvent * event) {
qDebug() << event << "in my graphics view (mousePressEvent).";
event->ignore();
}
Result for QPaintEvent, QMouseEvent, QKeyEvent and QWheelEvent:
-----------------------------------------------------------------------------------
QPaintEvent(0xbfc7714c) in filter.
QPaintEvent(0xbfc7714c) in my graphics view (event).
QPaintEvent(0xbfc76f0c) in my graphics view (paintEvent).
QMouseEvent(MouseButtonPress, 1, 1, 0) in my graphics view (mousePressEvent).
QMouseEvent(MouseButtonPress, 1, 1, 0) in filter.
QMouseEvent(MouseButtonPress, 1, 1, 0) in my graphics view (event).
QKeyEvent(KeyPress, 1000013, 0, """", false, 1) in filter.
QKeyEvent(KeyPress, 1000013, 0, """", false, 1) in my graphics view (event).
QKeyEvent(KeyPress, 1000013, 0, """", false, 1) in my graphics view (keyPressEvent).
QWheelEvent(120) in my graphics view (wheelEvent).
QWheelEvent(120) in filter.
QWheelEvent(120) in my graphics view (event).
I've implemented a sub class of QGraphicsView (MyGraphicsView). I want to install an event filter on this view which handles all "user events". But I've got some trouble with the event handling in Qt.
I thought the propagation order is always:
installed filter -> QObject::event()-> event-specific function (like paintEvent)
I've experienced that this is only true for some events like e.g. QPaintEvent and QKeyEvent in case of QMouseEvent or QWheelEvent the propagation order is:
event-specific function -> installed filter -> QObject::event().
So if I would like to filter QMouseEvents or QWheelEvents for my sub class of QGraphicsView I have to reimplement the event-specific functions (e.g. mouseMoveEvent) there I have to ignore() the event so that the installed filter receives the event. If not doing so the event filter doesn't receive these events.
To me this looks a bit strange. The Qt 4.5 Documentation says : "An event filter gets to process events BEFORE the target object does ..."
Is this a bug a feature or is there something wrong with my code?
I've attached a code snippet and the result for QPaintEvent, QMouseEvent, QKeyEvent and QWheelEvent.
Thank you in advance
Markus
PS: I'm using Qt 4.5.1.
#include "filterevents.h"
filterEvents::filterEvents(QWidget *parent)
: QWidget(parent)
{
// set up from with my graphics view
view = new MyGraphicsView();
layout = new QHBoxLayout();
layout->addWidget(view);
setLayout(layout);
// install event filter
view->installEventFilter(this);
}
bool filterEvents::eventFilter (QObject * object, QEvent * event)
{
if(event->type() == QEvent::KeyPress ||
event->type() == QEvent::Wheel ||
event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::Paint)
qDebug() << event << "in filter.";
return QObject::eventFilter(object, event);
}
#include "MyGraphicsView.h"
#include <QDebug>
MyGraphicsView::MyGraphicsView() {
setMouseTracking(true);
}
MyGraphicsView::~MyGraphicsView() {
}
bool MyGraphicsView::event(QEvent * event) {
if(event->type() == QEvent::KeyPress ||
event->type() == QEvent::Wheel ||
event->type() == QEvent::MouseButtonPress ||
event->type() == QEvent::Paint)
qDebug() << event << "in my graphics view (event).";
return QGraphicsView::event(event);
}
void MyGraphicsView::paintEvent(QPaintEvent * event) {
qDebug() << event << "in my graphics view (paintEvent).";
event->ignore();
}
void MyGraphicsView::wheelEvent(QWheelEvent * event) {
qDebug() << event << "in my graphics view (wheelEvent).";
event->ignore();
}
void MyGraphicsView::keyPressEvent(QKeyEvent * event) {
qDebug() << event << "in my graphics view (keyPressEvent).";
event->ignore();
}
void MyGraphicsView::mousePressEvent(QMouseEvent * event) {
qDebug() << event << "in my graphics view (mousePressEvent).";
event->ignore();
}
Result for QPaintEvent, QMouseEvent, QKeyEvent and QWheelEvent:
-----------------------------------------------------------------------------------
QPaintEvent(0xbfc7714c) in filter.
QPaintEvent(0xbfc7714c) in my graphics view (event).
QPaintEvent(0xbfc76f0c) in my graphics view (paintEvent).
QMouseEvent(MouseButtonPress, 1, 1, 0) in my graphics view (mousePressEvent).
QMouseEvent(MouseButtonPress, 1, 1, 0) in filter.
QMouseEvent(MouseButtonPress, 1, 1, 0) in my graphics view (event).
QKeyEvent(KeyPress, 1000013, 0, """", false, 1) in filter.
QKeyEvent(KeyPress, 1000013, 0, """", false, 1) in my graphics view (event).
QKeyEvent(KeyPress, 1000013, 0, """", false, 1) in my graphics view (keyPressEvent).
QWheelEvent(120) in my graphics view (wheelEvent).
QWheelEvent(120) in filter.
QWheelEvent(120) in my graphics view (event).