QGraphicsItem在添加到组时自定义选择 - 奇怪的不一致结果

时间:2015-10-13 21:13:43

标签: qt selection grouping qgraphicsitem qgraphicsscene

这个问题可能与$video_id = ...; $url = "http://www.youtube.com/watch?v=".$video_id; $page = file_get_contents($url); $doc = new DOMDocument(); $doc->loadHTML($page); $title_div = $doc->getElementById('eow-title'); $title = $title_div->nodeValue; var_dump($title); exit; 有关也可能没有关系 - 我以前从未见过这种行为.... 简要说明:我正在取消选择某个项目,但除非我致电只读$url = "http://www.youtube.com/watch?v=".$video_id; $doc = new DOMDocument(); $doc->preserveWhiteSpace = FALSE; $doc->loadHTMLFile($url); $title_div = $doc->getElementById('eow-title'); $title = $title_div->nodeValue; var_dump($title); exit; ,否则行动不会发生 - 即使我没有使用它。< / p>

详细信息:

我有一个自定义QGraphicsItemGroup类,必须在scene().selectedItems()上执行大量操作。

如果项目在一个组中,则不应在任何操作中使用它们 - 只应使用该组。

所以我创建了我的QGraphicsScene方法来执行我需要的东西:

selectedItems()

不幸的是,这些物品拒绝被取消选择!

然后,我在每行之后添加了调试消息 - 并发现添加调试消息会改变结果!

addToGroup()

调用void addToGroup(QList<QGraphicsItem *> children) { foreach(QGraphicsItem* child, children) { child->setSelected(false); QGraphicsItemGroup::addToGroup(child); } } - 应该只读 - 会使项目实际取消选择!

请允许我理解这一点!

完整示例代码:

void addToGroup(QList<QGraphicsItem *> children) {
    foreach(QGraphicsItem* child, children)
    {
        child->setSelected(false);
        scene()->selectedItems();        // this makes it work !
        QGraphicsItemGroup::addToGroup(child);
    }
}

1 个答案:

答案 0 :(得分:2)

关于scene().selectedItems()的良好观察。当此类项目添加到QGraphicsItem时,实际上还有一个与QGraphicsItemGroup项目选择状态不一致。

当选择selectedItems时,内部私有集QGraphicsItem似乎会累积项目。但是,如果未选择此类项目,则不会从该集合中删除该项目。

仅当调用函数QGraphicsItem并且该项的成员函数 QGraphicsScene::selectedItems()返回QGraphicsItem::isSelected() 时,才会从该集中删除

false

在您的情况下,首先将项目添加到私人场景选定集。然后,更改这些项目的选定标志,并将组对象添加到处于选定状态的该场景。因此,集合中有三个对象。诀窍是,现在isSelected()对于所有项目都是true,因为组中项目的 isSelected()始终返回与组isSelected()相同的结果,而与项目无关选定状态。因此,所有三个项目都显示在列表selectedItems()中。

如果在scene().selectedItems()之后调用child->setSelected(false),则会重新创建场景选定集并删除子项。这只会在selectedItems()中只有一个项目给出最终结果。

函数QGraphicsScene::selectedItems()非常繁重,因为它始终生成新的私有集。在foreach循环中调用它只是为了删除子项是不好的。通过更改group()函数中的调用顺序,可以实现相同的目标:

void group() {
    GroupItem* g = new GroupItem(items().size());
    // at first add items to group
    g->addToGroup(selectedItems());
    // add group to scene
    addItem(g);
    g->setSelected(true);
}

只在selectedItems()中提供一项。之所以发生这种情况,是因为将子项添加到不在场景中的组中时,这些项将从场景中删除。因此,它们也会从选定的集合中删除。然后将三个未选择的项目添加到场景中,但g->setSelected(true)仅将组添加到所选集合。

但是,如果在上面的示例中,您在addItem(g)之后致电setSelected(true),则会再次提供selectedItems()中的所有三项:

void group() {
    GroupItem* g = new GroupItem(items().size());
    g->addToGroup(selectedItems());
    g->setSelected(true);
    addItem(g);
}

发生这种情况,因为addItem(g)同时向场景中添加了三个项目。所有这三项都有isSelected()返回值true

另一个不一致与内部项目选择状态有关。似乎如果将一个项目添加到组中,该项目的状态将在添加到该组之前的状态中冻结。这意味着,如果您将所选项目添加到组,则它始终显示为已选中(带有虚线边界矩形),即使未选择该组也是如此。通过为该项调用setSelected(false)无法更改此类视图,因为现在该功能仅更改该组的选定状态。即使其isSelected()返回false,该项也可以显示为已选中。

看起来这些不一致性并非设计意图,并且在Qt bug跟踪器上报告它们是有意义的。