如何正确使用QQuickItem :: stackBefore()重新排序GridLayout中的项目?

时间:2014-12-27 22:40:58

标签: c++ qml

我在混合QML和C ++方面有相当丰富的经验,但是最近遇到了麻烦: 我在QML代码中有GridLayout项。最初我用C ++中的QQuickItems(实际上包含图标的矩形)填充它。这适用于渲染,包括大小调整,包装QML定义列:属性等。

现在我需要基于用户交互(鼠标点击矩形)在准确位置插入新的矩形(实际上就在单击的矩形之前)。我对MouseEvent传播没有任何问题,我甚至可以将任何大量的参数(无论是值或指向项目的指针)传递到我要处理的方法中。我只是找不到“c ++措辞”来使矩形真正重新排列。

我使用以下代码:

QQuickItem *icon = place(parent);
icon->stackBefore(insertBefore);
parent->update();   //(1)
GUI::programWindow->update(); //(2)
qDebug() << "\tCHILDS:" << parent->childItems(); //(3)

parent 是指向从QML代码传递的GridLayout项的指针(已验证它指向预期的位置)。 place(parent)是我的方法,它根据这个对象加载正确的图标,生成周围的矩形并返回指向它的指针(即*图标实际上是矩形)。 insertBefore 是指向同一GridLayout内的其他矩形的指针(通过我的onClick处理程序传递自定义信号)。仔细检查它是否是正确的GridLayout项目的子项。

现在我希望,那个首先被生成为最后一个GridLayout子节点的Rectangle,在预定的其他Rect和GridLayout之前传送“快速照明”(知道,视觉子命令改变了)将重新绘制到屏幕上。事实上,我面对新创建的Rect作为GridLayout项的最后一个。

有趣的是,第(3)行的输出显示了正确的,即重新排序的子女的顺序。因此,parent-&gt; childItems()的输出顺序与屏幕上显示的顺序不同。 注释(1)和(2)的行是我绝望的尝试使GridLayout重绘,但没有出现明显的变化。

有没有人有重新排序GridLayout孩子的经验?是否有其他更合适的方法来调用而不是stackBefore()?或者我错过了一些愚蠢的,立即可见的东西:)?

提前感谢任何线索。

1 个答案:

答案 0 :(得分:0)

您正在触发QQuickItem::update(),但是对于孩子来说,重新排序仅调用QQuickItem::polish()就足够了。根据{{​​3}}文档,QQuickItem::updatePolish()是通过QQuickItem::polish()进行final touch-up of items before they are rendered的调用来安排的。 但是polish事件应该安排在场景中最靠前的QQuickItem上,而不仅仅是父项。

另外,在使用Scene Graph and RenderingQQuickItem::stackBefore时,您需要注意两个重新排序的项目都应该是同一父QQuickItem实例的子项目。

如果要将QQuickItem插入子级列表的末尾,由于它是新添加项的默认位置,因此可以使用QQuickItem::stackAfter

总结一下,最终实现可能如下:

bool insertChild(QQuickItem* item, int position, QQuickItem* parent, QQuickItem* topmostItem) {
    if (!item || !parent || !topmostItem)
        return false;
    QList<QQuickItem*> children = parent->childItems();
    if (children.size() && children.size() > position) {
        QQuickItem* nextItem = children.at(position);
        item->setParentItem(parent);
        item->stackBefore(nextItem);
    } else {
        item->setParentItem(parent);
    }
    topmostItem->polish();
    return true;
}

除了QQuickItem::setParentItemQQuickItem::stackBefore以外,还可以单独使用QQuickItem::stackAfter,但是在这种情况下,复杂度是线性的:

...
QList<QQuickItem*> children = parent->childItems();
// Remove all children from parent from insert position and to the end
for (int index = position; index < children.size(); ++index) {
    children[index]->setParentItem(nullptr);
}
// Push back new QQuickItem into parent
item->setParentItem(parent);
// Push back into parent all previously temporary removed children
for (int index = position; index < children.size(); ++index) {
    children[index]->setParentItem(parent);
}
topmostItem->polish();
...