小编str*_*bly的帖子

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): …
Run Code Online (Sandbox Code Playgroud)

python qt pyside

5
推荐指数
1
解决办法
1022
查看次数

何时从QAbstractItemModel发出dataChanged

在Qt中,我有一个模型子类QAbstractItemModel- 它是一个在QTreeView中显示的树.

该模型支持各种形式的变更,这些变更都可行.两个相关性是:

1)少量相关行中的一些数据发生变化

2)可视化更改意味着大多数行应更改其格式 - 特别是它们会更改背景突出显示.他们的DisplayRole数据没有变化.

当前的设计以相同的方式处理这两个方面:对于每个有任何变化的行,模型都会发出dataChanged(start_of_row_index,end_of_row_index).我为两个更改的父行以及已更改的任何子项发出信号.

然而,当模型变大时,这在情况2中表现很差:dataChanged发射了大量信号.

我已经更改了代码,以便在案例2中,模型dataChanged仅针对作为整个树的父级的(单个)行发出.

这仍然可以正常工作,但不符合我对模型责任的理解.但我怀疑我可能错了.

也许我误解了这个dataChanged信号?它是否真的导致视图更新所有子项以及指定的范围?或者,dataChanged当它不是在DisplayRole变化时,我可以避免发射吗?

编辑我到目前为止的进展

正如Jan指出的那样,dataChanged在案例2中,我应该为大多数或所有行发射.

我的代码最初通过dataChanged为每个更改的行发出这个来做到这一点,但这太贵了 - 视图处理所有这些信号需要太长时间.

一种可能的解决方案可能是聚合dataChanged任何连续变化行块的信号,但是当例如每隔一行发生变化时,这仍然不能很好地执行 - 它仍然会发出太多信号.

理想情况下,我想告诉视图将所有数据视为可能已更改(但所有索引仍然有效 - 布局未更改).单个信号似乎不可能实现这一点.

由于类的怪癖QTreeView,只要有可能(虽然根据规范不正确)只发出一个dataChanged(tl,br)tl != br.我有这个工作,它通过了我们的测试,但让我感到紧张.

我现在已经解决了遍历树的版本并dataChanged(tl,br)为每个父级发出一个单独的版本(使用tl,br跨越该父级的所有子级).这符合模型/视图协议,对于我们的模型,它通常将信号数量减少大约10倍.

然而,它似乎并不理想.有人提出其他建议吗?

qt qtreeview qabstractitemmodel

4
推荐指数
1
解决办法
1万
查看次数

标签 统计

qt ×2

pyside ×1

python ×1

qabstractitemmodel ×1

qtreeview ×1