3

I have a Qt program with many buttons, user-interactable widgets, etc.
At one stage in the program, I would like all the widgets to temporarily 'stop working'; stop behaving to mouse clicks and instead pass the event on to one function.

(This is so the User can select a widget to perform meta operations. Part explanation here: Get variable name of Qt Widget (for use in Stylesheet)? )

The User would pick a widget (to do stuff with) by clicking it, and of course clicking a button must not cause the button's bound function to run.

What is the correct (most abstracted, sensible) method of doing this?
(which doesn't involve too much new code. ie; not subclassing every widget)
Is there anything in Qt designed for this?

So far, I am able to retrieve a list of all the widgets in the program (by calling

QObject.findChildren(QtGui.QWidget)

so the solution can incorporate this.

My current horrible ideas are;

  • Some how dealing with all the applications events all the time in one function and not letting through the events when I need the application to be dormant.
  • When I need dormancy, make a new transparent widget which recieves mouse clicks and stretch it over the entire window. Take coordinates of click and figure out the widget underneath.
  • Somehow create a new 'shell' instance of the window.

THANKS!
(Sorry for the terrible write-up; in a slight rush)


python 2.7.2
PyQt4
Windows 7

Community
  • 1
  • 1
Anti Earth
  • 4,671
  • 13
  • 52
  • 83

2 Answers2

4

You can intercept events send to specific widgets with QObject::installEventFilter.

graphite
  • 2,920
  • 22
  • 40
  • This is exactly the solution. If you want to 'steal' all events, put an event filter on the qApp and it'll keep any children from receiving them. – synthesizerpatel Jan 25 '12 at 08:20
  • event filtering did nothing. Even though all events are ignored, clicking the buttons still runs the functions! (Unless I'm stupid and don't know what I'm doing; true) – Anti Earth Jan 25 '12 at 11:48
  • 1
    If you want to stop events being processed further, make sure you return true from your eventFilter(). Also, filtering all events is a very bad idea - only filter user input. An even more straightforward way of achieving this would be to call setEnabled(false) on your top level widget. – Dan Milburn Jan 25 '12 at 17:14
1

graphite answered this one first so give credit where credit is due.

For an actual example in PySide, here's an example you might draw some useful code from:

my_app.py

from KeyPressEater import KeyPressEater

if __name__ == "__main__":
    app = QApplication(sys.argv)
    eater = KeyPressEater()
    app.installEventFilter(eater)

KeyPressEater.py

class KeyPressEater(QObject):

    # subclassing for eventFilter


    def eventFilter(self, obj, event):

        if self.ignore_input:
            # swallow events
            pass
        else:
            # bubble events 

        return QObject.eventFilter(self,obj,event)
Anti Earth
  • 4,671
  • 13
  • 52
  • 83
synthesizerpatel
  • 27,321
  • 5
  • 74
  • 91
  • Don't really understand the class structure. (How do you have an attribute of ignore_input? You didn't have a constructor for KeyPressEater). I'll certainly look into the eventFilter though. Thanks! – Anti Earth Jan 25 '12 at 10:37