Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt 如何从QGraphicscene获取有关addItem或itemChange的通知?_Qt_Notifications_Signals_Qgraphicsitem_Qgraphicsscene - Fatal编程技术网

Qt 如何从QGraphicscene获取有关addItem或itemChange的通知?

Qt 如何从QGraphicscene获取有关addItem或itemChange的通知?,qt,notifications,signals,qgraphicsitem,qgraphicsscene,Qt,Notifications,Signals,Qgraphicsitem,Qgraphicsscene,在我的项目中,我使用了一个qgraphicscene,并在整个代码中添加/删除项目 现在我想在添加或删除QGraphicsItem时得到通知。许多Qt类都有通知信号或至少是虚拟函数,这些函数在发生此类更改时会被调用。我试图避免在许多地方添加许多行代码,这不仅麻烦而且不安全(现在或将来忘记插入/删除) 我需要一个能与任何QGraphicsItem一起使用的解决方案 这是一个不起作用的事情列表: 连接到qgraphicscene的信号(如qabstractemmodel::rowsInserted

在我的项目中,我使用了一个
qgraphicscene
,并在整个代码中添加/删除项目

现在我想在添加或删除
QGraphicsItem
时得到通知。许多Qt类都有通知信号或至少是虚拟函数,这些函数在发生此类更改时会被调用。我试图避免在许多地方添加许多行代码,这不仅麻烦而且不安全(现在或将来忘记插入/删除)

我需要一个能与任何
QGraphicsItem
一起使用的解决方案

这是一个不起作用的事情列表:

  • 连接到
    qgraphicscene
    的信号(如
    qabstractemmodel::rowsInserted()
    )->没有信号
  • 继承自
    qgraphicscene
    并重载虚拟通知程序函数(如
    QTabWidget::tabInserted()
    )->没有
  • 继承并重载
    addItem()
    ,自己发送通知(如
    QMdiArea::addSubWindow()
    )->
    addItem
    不是虚拟的,从
    QGraphicsItems
    的构造函数调用
  • 在新添加的
    QGraphicsItems
    ->上安装事件筛选器不知道如何获取新添加的项目,它将是一个
    sceneEventFilter
    ,只能安装在其他
    QGraphicsItems
  • 连接到
    QGraphicsItem
    ->
    itemChange
    itemChange()
    不是信号,重载
    QGraphicsItem
    不是选项
  • 包装
    qgraphicscene
    (将场景作为私有成员)并仅公开函数
    addItem
    removietem
    ->,但该场景中的
    qgraphicssitems
    仍可以通过
    scene()
    函数访问它,因此此解决方案不够安全
如何获取有关项目更改的通知?


如果有一个简单的方法,我只是错过了,请告诉我。除此之外,我非常感谢您的建议。

我认为您最好连接到信号


它不会告诉您更改/添加/删除了哪些项目,因为它用于
QGraphicsView
更新显示。但是您应该能够通过使用提供的区域找到答案。

我意识到OP的一个要求是不要将该项子类化,但我希望这仍然可以帮助其他最终来到这里的人。Qt正在发送事件来完成此操作,它只需要扩展
itemChange
方法以“获得通知”。然后,您可以像这里的示例那样挂接回调方法,或者提供信号,或者您需要的任何东西

这是Python中的模式,但我确信它与C++中的模式相同:


我认为最好的方法就是包装QGraphicscene,并在包装器中提供您自己的
addItem()
函数。遗憾的是,您不能将
QGraphicsSitem
子类化,因为它的所有场景更改(包括场景添加/删除)都在
sceneEvent(QEvent*事件)中运行
method-它为您的问题提供了一个非常干净和可调的解决方案。@pmr正如我所说的,
addItem()
函数不是虚拟的,它是从
QGraphicsItem
s的构造函数调用的。所以这不是一个完整的解决方案。我认为pmr的意思是你可以编写一个包含QGraphicsView的类,而不是继承它。该类不会授予对视图的公共访问权限,因此项目的创建者必须调用自己的addItem函数。显然,您无法再通过构造函数提供场景(因为无法从包装器中获取()),您必须更改当前添加到场景中的项目的每一行。@TimMeyer这仍然是不安全的,因为QGraphicsSitems和QGraphicsView都知道它们的场景()-例如用于
场景()->removeItem(这个)
-我仍然无法阻止它,或者至少无法得到有关它的通知。
def itemChange(self, change, value):
    """
    Runs if this item has the `ItemSendsGeometryChanges` flag set.

    This doesn't "accept" any of the changes, it is only to add hooks.
    """
    if change == QtWidgets.QGraphicsItem.ItemSceneChange:
        # The value for this event is the scene. None means the item was removed.
        if value:
            self.onAddedtoScene(value)
        else:
            self.onRemovedFromScene()

    return super(SceneNodeBase, self).itemChange(change, value)