问题 QGraphicsItem :: prepareGeometryChange()如何工作?


根据Qt文档,它“为几何变化准备项目。在更改项目的边界矩形之前调用此函数以使QGraphicsScene的索引保持最新。如果有必要,prepareGeometryChange()将调用update()。”

我不明白的是QGraphicsItem如何知道边界矩形何时发生变化,以及它如何知道何时调用update()。您是否应该在调用prepareGeometryChange()然后更改边界矩形后自己调用update()?

我非常欣赏对一些看似透视的方法有所了解。


10301
2018-03-23 03:01


起源



答案:


  • QGraphicsItem如何知道边界矩形何时发生变化?

我认为 你懂。假设您有一个QGraphicsItemGroup聚合了几个子项,并且您希望一次只显示一个子项。组项的边界矩形需要与当前所选项的边界矩形相同:

QRectF MyItemGroup::boundingRect() const
{
    QRectF rect;
    if (currentItem_) {
        rect = currentItem_->boundingRect();
    }
    return rect;
}

假设您有一种方法可以更改必须显示哪个子项:

void MyItemGroup::setCurrentItem(MyItem * item)
{
    if (list_of_items_.contains(item)) {
        prepareGeometryChange();
        currentItem_ = item;
    }
}

如果你注释掉prepareGeometryChange,视图将不会再次询问MyItemGroup的边界rect,并且项目的更新(在其他地方触发)将涉及错误的rect。

  • 怎么知道何时调用update()?

根据QGraphicsItem的消息来源,里面的 prepareGeometry 仅在两种情况下调用方法更新:

  1. 如果有人连接到 changed 信号
  2. 如果场景没有视图

更多细节 这里

  • 您是否应该在致电后自己致电update() prepareGeometryChange()然后更改边界矩形?

我认为答案是 没有。除了电话 updateprepareGeometryChange 将场景中的项目区域标记为脏,从而导致重新绘制区域本身。根据我的经验,这足以满足100%的情况,所以我不需要调用update()。


16
2018-03-23 09:06



更一般地说,你可以精确地在每次输入时调用它 ::boundingRect() 计算变化。你的例子是正确的。 - azf
感谢您的回答。但是,我仍然在想 怎么样 有用。例如,什么时候调用update()? - Anthony
答案更新,希望这有帮助。 - Masci
再次感谢,抱歉延迟! - Anthony


答案:


  • QGraphicsItem如何知道边界矩形何时发生变化?

我认为 你懂。假设您有一个QGraphicsItemGroup聚合了几个子项,并且您希望一次只显示一个子项。组项的边界矩形需要与当前所选项的边界矩形相同:

QRectF MyItemGroup::boundingRect() const
{
    QRectF rect;
    if (currentItem_) {
        rect = currentItem_->boundingRect();
    }
    return rect;
}

假设您有一种方法可以更改必须显示哪个子项:

void MyItemGroup::setCurrentItem(MyItem * item)
{
    if (list_of_items_.contains(item)) {
        prepareGeometryChange();
        currentItem_ = item;
    }
}

如果你注释掉prepareGeometryChange,视图将不会再次询问MyItemGroup的边界rect,并且项目的更新(在其他地方触发)将涉及错误的rect。

  • 怎么知道何时调用update()?

根据QGraphicsItem的消息来源,里面的 prepareGeometry 仅在两种情况下调用方法更新:

  1. 如果有人连接到 changed 信号
  2. 如果场景没有视图

更多细节 这里

  • 您是否应该在致电后自己致电update() prepareGeometryChange()然后更改边界矩形?

我认为答案是 没有。除了电话 updateprepareGeometryChange 将场景中的项目区域标记为脏,从而导致重新绘制区域本身。根据我的经验,这足以满足100%的情况,所以我不需要调用update()。


16
2018-03-23 09:06



更一般地说,你可以精确地在每次输入时调用它 ::boundingRect() 计算变化。你的例子是正确的。 - azf
感谢您的回答。但是,我仍然在想 怎么样 有用。例如,什么时候调用update()? - Anthony
答案更新,希望这有帮助。 - Masci
再次感谢,抱歉延迟! - Anthony