我有一个^{
所以我在PySide
中实现了这一点,我认为它工作得很好:当你点击圆圈时,它们会很好地变成正方形。在
直到我在视图中使用RubberBandDrag
选择。当橡皮筋选择到达父对象并且选择发生更改时,这将导致即时分段错误。这可能是因为QT中的橡皮筋选择在某种程度上保持了指向子项的指针,该子项在橡皮筋选择操作完成之前就消失了。在
下面的简化代码-首先单击对象(它会很好地更改),然后在对象上拖动-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_()
所以问题:
我刚刚犯了一个可以直接纠正的错误吗?在
或者在处理ItemSelectedHasChanged
事件时不允许从场景中移除对象?在
有没有一个方便的解决办法?或者什么是一个好的替代方法?我可以将QGraphicsRectItem
替换为一个自定义项,该项可以绘制为正方形或圆形,但这并不能方便地涵盖我的所有用例。我知道我可以做到这一点,但肯定不会那么简单。在
编辑-解决方法:
可以通过将要删除的对象保留一段时间来防止这种失败。可以这样做:
^{pr2}$然而,这是一个丑陋的代码,增加了内存的使用,却没有真正的好处。相反,我转而使用QGraphicsScene.selectionChanged
信号,正如this答案中建议的那样。在
我已经调试过了。转载于Lunix
qt-everywhere-opensource-src-4.8.6/src/gui/graphicsview/qgraphicscene.cpp:2381在
^{pr2}$他们正在使用
items()
函数查找橡皮筋选择下的项目列表。如果一个指针在处理某个项目时变为无效,则删除该指针。{next}导致调用^崩溃。在作为替代,您可以使用
QGraphicsScene::selectionChanged
信号。每次选择更改仅发射一次。在看来Qt并不认为
itemChange
会有一些重大变化在这后面是您在
prepareGeometryChange()
调用时的常见错误。在它被设计为在更改
boundingRect
之前调用。Bounding rect应该是调用prepareGeometryChange
时的旧矩形,然后是新的。在所以这可能发生:
在
updateContents
中:添加子元素后,它再次调用
boundingRect
,但值意外不同。在作为解决方案,您可以添加一个变量
相关问题 更多 >
编程相关推荐