我有一個QGraphicsScene
包含一些簡單的對象(在這個簡化的示例圓),我想改變成其他對象(這裏正方形)選中時。更具體地說,我希望有父對象,它們不繪製自己,它們是由他們的子對象繪製的,並且在各種情況下,但特別是在選擇父對象時,我希望這些子對象集更改。這是我正在開發的整個應用程序的一個很好的概念框架。QGraphicsScene改變對象時,選擇
所以我已經在PySide
中實現了這個,我認爲它工作的很好:當你點擊它們時,圓圈會很好地變成正方形。
直到我在視圖中使用RubberBandDrag
選擇。當橡皮筋選擇到達父對象並且選擇改變時,這會導致即時段錯誤。據推測,這是由於QT中的橡皮筋選擇以某種方式保持指向在橡皮筋選擇動作完成之前正在消失的子物品的指針而觸發的。
簡化的代碼如下 - 首先單擊對象上測試它(它改變了很好的),然後拖過對象 - 段錯誤:
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_()
所以問題:
難道我只是做了一個錯誤,可以直接修復?
或者在處理ItemSelectedHasChanged
事件時不允許從場景中移除物體?
是否有一個方便的解決方法?或者什麼是一個好的替代方法?我可以用一個自定義項目代替QGraphicsRectItem
,該項目可以以方形或圓形繪製,但不能方便地覆蓋我所有的用例。我可以看到我可以完成這項工作,但肯定不會那麼簡單。
編輯 - 解決方法:
有可能通過保留大約要被刪除的對象的同時,防止這種失敗。這可以通過東西就像這樣:
def updateContents(self):
self.prepareGeometryChange()
self._temp_store = self.childItems()
for c in self.childItems():
self.scene().removeItem(c)
...
然而,這是醜陋的代碼,並增加了沒有實際的好處內存使用情況。相反,我已經轉向使用QGraphicsScene.selectionChanged
信號,建議在this的答案。
什麼版本?我只是試了一下,沒有問題。 – eyllanesc
好問題 - Python的2.7.11- PySide 1.2.4 - 所有的Windows 8.1 – strubbly
我使用python 2.7.13和1.2.4 PySide,你是什麼操作系統,你運行它通過IDE,如果是的話?它是什麼? – eyllanesc