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

Posted

技术标签:

【中文标题】如何正确使用 QQuickItem::stackBefore() 重新排序 GridLayout 中的项目?【英文标题】:How to properly use QQuickItem::stackBefore() to reorder items in GridLayout? 【发布时间】:2014-12-27 22:40:58 【问题描述】:

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

现在我希望,最初作为最后一个 GridLayout 子级生成的 Rectangle 在预期的其他 Rect 和 GridLayout(知道视觉子级顺序已更改)将重新绘制新的排列到屏幕之前得到“快速照明”传送。事实上,我面对新创建的 Rect 作为 GridLayout 项目的最后一个可见。

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

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

提前感谢任何线索。

【问题讨论】:

【参考方案1】:

您正在触发QQuickItem::update(),但对于儿童来说,只需调用QQuickItem::polish() 就足够了。根据Scene Graph and Rendering doc,QQuickItem::updatePolish() 是通过调用QQuickItem::polish() 来安排final touch-up of items before they are rendered 的。 但是polish 事件应该安排在场景中最顶部的 QQuickItem 而不仅仅是父项。

此外,当使用QQuickItem::stackBefore 或QQuickItem::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::stackBefore 和QQuickItem::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();
...

【讨论】:

以上是关于如何正确使用 QQuickItem::stackBefore() 重新排序 GridLayout 中的项目?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用 Composer 安装 Laravel 扩展包

如何正确的使用SharedPreferences

如何正确强制正确使用类方法?

如何正确使用 Composer 安装 Laravel 扩展包

如何正确使用 AsyncTask? [关闭]

如何正确的使用QWebEngineView