PDA

View Full Version : Event filter: very confused about how they work



papillon
19th November 2011, 16:44
I've read documentation about event filters and have been have to install a filter for a glFrame control, that triggers on keypress events.

But I can't see how to apply the same event filter for another control, because from what I can understand it seems like one has to create a new class for it.

Could you please give me some hints? Thank you very much...

Oleg
19th November 2011, 17:23
You can simply install the same class as event filter for any other widget:


otherWidget->installEventFilter(this);

papillon
19th November 2011, 17:28
Thanks Oleg. This lead me to another question: how would you create 2 or more filters, and install those for widgets of the same class?

Oleg
19th November 2011, 17:38
If you want to handle events in two or more different event filters, then you should simply install all of the filters for given widgets and be sure to return false from eventFilter functions to prevent end of event processing.

d_stranz
19th November 2011, 17:47
You want two or more event filters for the *same* widget? Or are you asking whether you can have two or more different event filters, and install one on PushButton1 and another on PushButton2, etc.? Both can be done.

Event filters are installed on an instance by instance basis. They affect only the specific QObject instance that they are installed on.

You can have multiple event filters per object instance. The one that was installed last gets called first.
You can use the same event filter for multiple object instances. The eventFilter() method tells you which object is the one to which the event applies.

An event filter is basically telling the event loop, "Before you send the event to the object that should receive it, send it to me first, and I can look at it and tell you what to do with it". The return value from the event filter is what tells the event loop whether to pass the event along to the actual receiver or to eat it. If multiple filters are installed on the same object instance, then each one of them gets a whack at it (unless an event filter earlier in the chain killed it). If no one kills the event, then the actual object (like the push button) finally gets to see it.

Note that the Graphics / View framework does things a bit differently. Events get sent to the scene first, then forwarded to the appropriate graphics item. If you install an event filter on the QGraphicsView, it never gets invoked. There is a way around this (subclass QGaphicsView and in the event handler, ignore() the event). But I am pretty sure that having to do this means a misunderstanding on my part about how the G/V frameworks handles events, so I still have some learning to do.

papillon
19th November 2011, 17:58
I would like to define and use multiple filters on different widgets. So for example, have a filter installed to a QFrame to intercept when the mouse is over, and a another event filter to another QFrame to intercept other actions.

d_stranz
19th November 2011, 18:12
So all you have to do is something like this:



class Filter1 : public QObject
{
Q_OBJECT;

public:
bool eventFilter( QObject * object, QEvent * event )
{
//... examine the event and return true or false
}
};

class Filter2 : public QObject
{
Q_OBJECT;

public:
bool eventFilter( QObject * object, QEvent * event )
{
//... examine the event and return true or false
}
};

// Somefile.cpp

QFrame * frame1 = new QFrame( this );
QFrame * frame2 = new QFrame( this );

Filter1 * filter1 = new Filter1( this );
Filter2 * filter2 = new Filter2( this );

frame1->installEventFilter( filter1 );
frame2->installEventFilter( filter2 );


So now all events for frame1 will be sent first to the filter1 instance of Filter1, likewise for frame2. If either filter eats the event, the respective frame will not see it. Otherwise, after the filter is done with it, the event will then be forwarded to the frame. In the eventFilter() method for filter1, the QObject argument will point to frame1, likewise for filter2.

papillon
19th November 2011, 18:22
Ah that how is done! Thanks so much, I was quite lost trying to find that out!

d_stranz
20th November 2011, 01:46
Note that the Graphics / View framework does things a bit differently. Events get sent to the scene first, then forwarded to the appropriate graphics item. If you install an event filter on the QGraphicsView, it never gets invoked. There is a way around this (subclass QGaphicsView and in the event handler, ignore() the event). But I am pretty sure that having to do this means a misunderstanding on my part about how the G/V frameworks handles events, so I still have some learning to do.

I wrote this earlier, but reading another post lead me to the solution: For a QGraphicsView, install the even filter on the QGraphicsView's viewport() widget, not on the QGraphicsView itself. If you do this, the event filter works as expected. Learning accomplished!