[PyQt] Overriding (hooking) an event() function: QWidget vs QGraphicsWidget

Phil Thompson phil at riverbankcomputing.com
Sat Jan 2 11:22:51 GMT 2010


On Sat, 2 Jan 2010 13:15:52 +0300, z <zoomer.gm at gmail.com> wrote:
> Hello everybody, and happy new year!
> to the point:
> In python it is possible to override some method of an instance,
> assigning to a "instance.methodname" a new value (which must be
> callabe with the same number of arguments, to be useful)
> For example i'd like to intercept events, coming to some widget,
> having this widget instance. It is easy to achieve, if i define this
> widget's class myself, and therefore can redefine event() method in
> class definiion. But suppose, that i just providing an interface for
> using by other parties. One, who using it only give me an instance,
> which class definition i can not control.
> This is an example program, which defines a hook function, and
> replaces instance's original event() method with it (for the start we
> will see how it works for QGraphicsWidget):
> ###########################
> from PyQt4 import QtGui, QtCore
> 
> app = QtGui.QApplication(sys.argv)
> 
> # suppose this class is defined somewhere else
> class Target(QtGui.QGraphicsWidget):
>     def __init__(self):
>         QtGui.QGraphicsWidget.__init__(self)
> 
> target = Target()
> target.show()
> 
> eventOrig = target.event
> 
> # intercept function, which just prints incoming event type, and
> passes further processing to original event()
> def eventHook(ev):
>     print 'HOOK', ev.type()
>     return eventOrig(ev)
> 
> target.event = eventHook
> 
> # Let's trigger an event()
> QtGui.QApplication.postEvent(target,
> QtCore.QEvent(QtCore.QEvent.LayoutRequest))
> target.resize(200,200)
> 
> sys.exit(app.exec_())
> ############################
> 
> Of course, it is not fully complete and sane code, but it
> demonstrates, that this approach works fine. This is console output of
> this program:
> ###########
> HOOK 181
> HOOK 76
> ############
> (181 is QEvent.GraphicsSceneResize, and 76 is layoutrequest ) So it
> works for QGraphicsWidget.
> But it does not work for QWidget. i.e. if the class is defined as:
> ############
> class Target(QtGui.QWidget):
>    def __init__(self):
>        QtGui.QWidget.__init__(self)
> #############
> Nothing appears on output at all. But the program runs flawlessly,
> (and shows main window, containing this widget)
> 
> So the question is: what's the difference? Why it works for
> QGraphicsWidget, but not QWidget? Is it some peculiarities of Qt event
> processing? Or is it PyQt? Or is it my system config or installed
> software gone wrong?
> 
> P.S: running system config:
> - linux x86_64
> - python 2.6
> - PyQt 4.6.2
> - Qt 4.6

PyQt caches lookups for Python reimplementations of methods. Monkey
patching will only work if you patch a method before it is looked up for
the first time. Your example will work for QWidget if you move the call to
show() after you patch it.

Phil


More information about the PyQt mailing list