English 日本語

PySide Pitfalls

This Wiki page lists common pitfalls that you might step into when starting out with PySide development. If you experience some “Oh!” moment while developing your apps using PySide, please document the issue here.

References

If a QObject falls out of scope in Python, it will get deleted. You have to take care of keeping a reference to the object:

  • Store it as an attribute of an object you keep around, e.g. self.window = QMainWindow()
  • Pass a parent QObject to the object’s constructor, so it gets owned by the parent

This does not work:

  1. class MyStuff(object):
  2.     # ...
  3.     def animate_stuff(self, target):
  4.         animation = QtCore.QPropertyAnimation(target, 'rotation')
  5.         animation.setDuration(700)
  6.         animation.setEasingCurve(QtCore.QEasingCurve.OutSine)
  7.         animation.setEndValue(100)
  8.         animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)

The reason for this is that the animation will get deleted at the end of animate_stuff(), so it does not really get the chance to do anything. In the case of animations (which usually have a target QObject), it’s a good idea to make it a child of the parent by giving the parent as last argument to the constructor:

  1. class MyStuff(object):
  2.     # ...
  3.     def animate_stuff(self, target):
  4.         animation = QtCore.QPropertyAnimation(target, 'rotation', target)
  5.         # ...

This will work, because the animation reference is now owned by “target”. Another option is to save the animation as an attribute of the object (using “self.animation = …”). This way, the reference to the animation is kept around as long as the object that has the attribute (if it does not get deleted manually before). Be aware that overwriting the attribute (e.g. with another animation while the first animation is still running) will again cause all references for the object to be removed, therefore deleting the object again.

QtCore.QObject.sender()

If you want to get the object that emitted a signal, you can do so using QtCore.QObject.sender(), although you should really think twice before using it (see the API docs of QObject for details). If you really, really decide that you have to use it, be aware that right now, you cannot call it as a static method, but only from within a QObject slot.

This means that the following code won’t work:

  1. def on_signal(*args):
  2.     print args
  3.     print QtCore.QObject.sender() # THIS DOES NOT WORK!
  4.  
  5. a.someSignal.connect(on_signal)

To achieve the same effect, you have to create a QObject subclass with a Slot and access sender() as a member method of your object, like this:

  1. class Listener(QtCore.QObject):
  2.     @QtCore.Slot()
  3.     def on_signal(self, *args):
  4.         print args
  5.         print self.sender()
  6.  
  7. listener = Listener()
  8. a.someSignal.connect(listener.on_signal)

Categories: