I have QGraphicsSceneone containing a few simple objects (in this simplified example of circles) that I want to change to other objects (here squares) when I select. More specifically, I would like to have parent objects that are not drawn by myself, they are drawn by their child objects and under various circumstances, but, in particular, when the parent objects are selected, I would like the set of child objects to change. This is a good conceptual framework for the general application I'm working on.
So, I implemented this in PySide, and I thought it was working fine: the circles are typed into squares when you click on them.
While I do not use the choice RubberBandDragin the view. This leads to instant segfault when the rubber band selection reaches the parent object and the selection changes. Presumably, this is because the selection of the rubber band in QT somehow holds the pointer to the child element, which disappears before the completion of the rubber band selection action.
The simplified code is below - check it by first clicking on the object (it changes beautifully), then dragging the object - segfault:
from PySide import QtCore,QtGui
class SceneObject(QtGui.QGraphicsItem):
def __init__(self, scene):
QtGui.QGraphicsItem.__init__(self, scene = scene)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QtGui.QGraphicsItem.ItemHasNoContents, True)
self.updateContents()
def updateContents(self):
self.prepareGeometryChange()
for c in self.childItems():
self.scene().removeItem(c)
if self.isSelected():
shape_item = QtGui.QGraphicsRectItem()
else:
shape_item = QtGui.QGraphicsEllipseItem()
shape_item.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, False)
shape_item.setFlag(QtGui.QGraphicsItem.ItemStacksBehindParent,True)
shape_item.setPen(QtGui.QPen("green"))
shape_item.setRect(QtCore.QRectF(0,0,10,10))
shape_item.setParentItem(self)
def itemChange(self, change, value):
if self.scene() != None:
if change == QtGui.QGraphicsItem.ItemSelectedHasChanged:
self.updateContents()
return
return super(SceneObject,self).itemChange(change, value)
def boundingRect(self):
return self.childrenBoundingRect()
class Visualiser(QtGui.QMainWindow):
def __init__(self):
super(Visualiser,self).__init__()
self.viewer = QtGui.QGraphicsView(self)
self.viewer.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
self.setCentralWidget(self.viewer)
self.viewer.setScene(QtGui.QGraphicsScene())
parent_item = SceneObject(self.viewer.scene())
parent_item.setPos(50,50)
app = QtGui.QApplication([])
mainwindow = Visualiser()
mainwindow.show()
app.exec_()
So the questions are:
I just made a mistake that can be directly fixed?
Or is it not allowed to delete objects from the scene when processing an event ItemSelectedHasChanged?
? ? QGraphicsRectItem , , , . , , , , .
. :
, , - . :
def updateContents(self):
self.prepareGeometryChange()
self._temp_store = self.childItems()
for c in self.childItems():
self.scene().removeItem(c)
...
. QGraphicsScene.selectionChanged, this.