PDA

View Full Version : Request for comment: Post event filter



wysota
5th March 2008, 20:22
Hi people. I just came up with an idea I consider worthy of adding to Qt and I'm going to submit it as a suggestion to Trolltech. But before I do, I'd like to know your opinions on it and possible usecases of the solution. Please take time to think about it and write your ideas and comments in this thread. Of course I'm open for criticism :cool:

The idea is to have something similar to eventFilter() and friends but different in that way that it is executed after the event has been delivered (contrary to eventFilter that is executed before the event has been delivered). My example usecase is demonstrated with the code below and the screenshot attached.

Also attached you'll find a file containing a macro that emulates "post event filters" on "user" level for single widget classes. To use it just include it in your code, make a widget subclass and add a WW_POSTEVENTFILTER macro just below the Q_OBJECT macro. When implementing postEventFilter() remember that it has to be a public slot (I'm using invokeMethod() to call the method without knowing its class name).

Here is an example:

#include "posteventfilter.h"

class PushButton : public QPushButton {
Q_OBJECT
WW_POSTEVENTFILTER(QPushButton)
public:
PushButton(QWidget *parent=0) : QPushButton(parent){}
};

class Dummy : public QObject {
Q_OBJECT
public:
Dummy(bool tl, QObject *parent=0) : QObject(parent){ m_tl = tl;}
public slots:
virtual bool postEventFilter(QObject *o, QEvent *e){
if(e->type()==QEvent::Paint){
QWidget *w = (QWidget*)o;
QPainter p(w);
QPen pe = p.pen();
pe.setColor(m_tl ? Qt::red : Qt::blue );
pe.setWidth(3);
p.setPen(pe);
p.setRenderHint(QPainter::Antialiasing);
if(m_tl){
p.drawLine(0,0, w->width(), w->height());
} else {
p.drawLine(w->width(), 0, 0, w->height());
}
return false;
}
return false;
}
private:
bool m_tl;
};

#include <QApplication>

int main(int argc, char **argv){
QApplication app(argc, argv);
Dummy d(true);
Dummy u(false);
PushButton pb;
pb.setText("TESTING");
pb.installPostEventFilter(&d);
pb.installPostEventFilter(&u);
pb.show();
return app.exec();
}

BTW. The code is not idiot-proof :) For instance don't try deleting object registered as filters to other objects.

jacek
5th March 2008, 21:20
For instance don't try deleting object registered as filters to other objects.
And don't try to use that macro for a class that doesn't inherit QPushButton. :p

Anyway it's nice and it looks similar to Java event handlers, but wouldn't it encourage people to create inefficient solutions? Like having decorators that paint on widgets (each with its own painter) instead of having proper custom widget. Situation is a bit similar to QxxxWidget classes --- first you use QxxxWidget because it's simplier, but then when code gets more complex you don't have time to switch to proper solution.

wysota
5th March 2008, 22:59
And don't try to use that macro for a class that doesn't inherit QPushButton. :p
Baah... you're right, I missed the fact that I'm calling the base class implementation... Probably this can only be done in Qt kernel by implementing this on QObject level...


Anyway it's nice and it looks similar to Java event handlers, but wouldn't it encourage people to create inefficient solutions?
Hmm... Not more than regular event filters, right?


Like having decorators that paint on widgets (each with its own painter) instead of having proper custom widget.
Actually in Qt the painter is shared across calls, so that's not an issue. And the code I provided is only a use case - provide an overlay for a widget (I don't like using QPixmap::grabWidget). I can imagine it being used for drawing rubber bands too. There are probably other use-cases not related to drawing, that's why I posted this thread in the first place...


Situation is a bit similar to QxxxWidget classes --- first you use QxxxWidget because it's simplier, but then when code gets more complex you don't have time to switch to proper solution.

I think it depends on what you are doing. I don't think event pre-filters are misused, so the probability of event post-filters (or rather post-hooks as the event is not being discarded) being misused is more or less similar.

Ok, I'm uploading a modified code so that it works with any object class, not only QPushButton ;) Now you have to pass the superclass name derived from QObject as a parameter to the macro.

jacek
7th March 2008, 21:55
I don't think event pre-filters are misused, so the probability of event post-filters (or rather post-hooks as the event is not being discarded) being misused is more or less similar.
I'm not comparing pre- and post-filters. I just wonder whether people won't choose such post-filter instead of reimplementing an event handler.

Your post-filter would prove themselves if there were some generic handlers/decorators that could be attached to different objects.