PDA

View Full Version : Handling QMouseEvents



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

wysota
24th June 2009, 15:21
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().


No, it's not. But it is the viewport() that is the destination of the event and the event gets delegated to the view itself thus first the event handler from the view gets called and if it doesn't handle the event then the event gets propagated to the parent and then is caught by the event filter. Install the event filter on the viewport() and it will work as expected.