我在混合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)是我的方法,该方法基于此对象加载适当的图标,生成周围的矩形并返回指向它的指针(即* icon实际上是Rectangle)。
insertBefore是指向同一GridLayout中其他矩形的指针(通过我的onClick处理程序传递的自定义信号)。再次检查它是否是正确的GridLayout项的子项。

现在,我可以期望,首先作为GridLayout子级的最后一个生成的Rectangle,在预期的其他Rect和GridLayout(知道视觉子级的顺序已更改)将重新绘制新布局到屏幕之前,会“快速发光”。实际上,我面对着新创建的Rect,它是GridLayout项的最后一个。

有趣的是,第(3)行的输出显示了正确的子级排序。因此,parent-> childItems()的输出顺序与屏幕上显示的顺序不同。
注释的行(1)和(2)是我拼命尝试使GridLayout重绘,但是没有出现可见的变化。

是否有人对GridLayout子项重新排序有经验?还有其他更合适的方法来代替stackBefore()吗?还是我缺少一些愚蠢的,立即可见的东西:)?

在此先感谢您提供任何线索。

最佳答案

您正在触发QQuickItem::update(),但是对于 child 重新排序,只需调用QQuickItem::polish()就足够了。根据Scene Graph and Rendering doc,QQuickItem::updatePolish()通过QQuickItem::polish()调用final touch-up of items before they are rendered进行调度。
但是polish事件应该安排在场景中最靠前的QQuickItem上,而不仅仅是父项。

此外,在使用QQuickItem::stackBeforeQQuickItem::stackAfter时,您需要注意两个重新排序的项目都应该是同一父QQuickItem实例的子项。

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

综上所述,最终实现可能如下所示:

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::stackBeforeQQuickItem::stackAfter的替代,可以单独使用QQuickItem::setParentItem,但是在这种情况下,复杂度是线性的:
...
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();
...

关于c++ - 如何正确使用QQuickItem::stackBefore()对GridLayout中的项目重新排序?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27672119/

10-10 00:59