I have a simple program which create a QGraphicsScene / View then execute a given file (via the exec statement of python) with some globals function export.
My aim is to only define code of the scene in new files, with some helpers function already defined.
I also have in my main program a thread which deliver callbacks, and i want to do some stuff on qgraphicsitems on callbacks.
The example here define an animation of invisibility linked to one callback:
from PySide import QtGui
# definition of an animation of invisibility
class AnimInvisible:
def __init__(self, item):
self.item = item
def on_callback(self, tag):
self.item.setVisible(tag.getProperty() != 0)
# creation of a simple QGraphicsRectItem
mon_rect = QtGui.QGraphicsRectItem(400, 300, 100, 50)
mon_rect.setBrush(QtGui.QBrush(QtGui.QColor('red')))
# this will add the rect to the scene defined in the file
# where the exec statement is done (exported by exec)
addItem(mon_rect)
a = AnimInvisible(mon_rect)
# this connect the a.on_callback on some changes from a thread. (exported from exec)
addCallback(a.on_callback, 'system:cmdamg')
And this works very well. But now, if I put the code of AnimInvisible in another module - say animations - and I replace in the above by:
from animations import AnimInvisible
I got an error, saying that Internal C++ object (PySide.QtGui.QGraphicsRectItem) already deleted..
It's a really weird behavior that I don't understand. I also tried with PyQt instead of PySide and I get the same behavior (object deleted when the code of AnimInvisible is in a module, and no problem if it is in the same file).
Thanks to your comments alexisdm and varela, i found the problem.
I was doing something like this:
class Synoptique:
def __init__(self, w, h):
self.view = QGraphicsView()
self.scene = SynopScene()
# some initialization ...
def openSynop(buApp, fname, w, h):
synop = Synoptique(w, h)
var_export = {
'addItem': synop.addItem,
'addCallback': buApp.addCallback,
}
exec open(fname) in var_export
synop.view.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
# buApp creation
openSynop(buApp, 'synop.py', 800, 600)
app.exec_()
But it appears that the reference to the synop object (containing QGraphicsView and Scene) is lost, because it is a local variable in the openSynop function. So references to QGraphicsView, scene, and objects in the scene where lost too.
One way to handle that is to declare the synop instance outside of the function, in the main call, or to return and save the synop reference from the function. This has solved my problem for example:
def openSynop(buApp, fname, w, h):
# same as before...
return synop
if __name__ == '__main__':
# same as before...
s = openSynop(buApp, 'synop.py', 800, 600)
app.exec_()
I now understand that I have to keep a reference on QGraphicsView / scene in order to manipulate later the QGraphicsItem which is inside the scene... Wow it was not obvious for me, thanks again !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With