【问题标题】:QML Repeater parentnessQML 中继器亲子关系
【发布时间】:2014-02-07 09:02:24
【问题描述】:

假设我有 2 种类型的自定义元素 - 父元素和子元素

场景中可以有多个父级

简单的场景是这样的:

Parent {
    Child {
        id: child1
    }
    Child {
        id: child2
    }
}

加载场景后,我想初始化父类中的所有子类:

void InitializeChildren() {
    list = findChildren<Child*>(QString(),Qt::FindChildrenRecursively);
    foreach(Child * child,list) {
        InitChild(this,child);
}

但是在更复杂的场景下失败了:

Parent {
    Rectangle {
        Repeater {
            model: 10
            delegate: Child {
            }
        }
    }    
}

只是因为 Repeater 没有 Childs 对象作为子对象。 所以我的问题 - 如果我确切知道它们是指定父级的嵌套子级,我如何获取所有子级的对象?

【问题讨论】:

    标签: c++ qml qt-quick qtquick2


    【解决方案1】:

    好吧,我想通了: Qt5 中发生了变化,这使得将 findChildren() 用于 Repeater 子级不再可用。查看qquickrepeater.cpp 后,发现Repeater 调用QQuickItem::setParentItem() 给创建的子代表。因此原始父母和孩子保持不变,但“视觉”父母是中继器的父母。

    TLDR: 不要在 Qt5 中使用findChildren() 来浏览项目场景图。相反,请使用以下内容:

    void getAllSearchTypes(QQuickItem *parent, QList<SearchType *> &list) {
    
     QList<QQuickItem *> children = parent->childItems();   
      foreach (QQuickItem *item, children) {
        SearchType *searchObject = dynamic_cast<SearchType *>(item);
        if (seachObject) list.append(searchObject);
        // call recursively and browse through the whole scene graph
        getAllSearchTypes(item, list);
     } 
    }
    

    然后像这样调用函数:

    QList<SearchType *> list;
    getAllSearchTypes(rootItem, list);
    // list now contains all objects of type SearchType, recursively searched children of rootItem
    

    SearchType 替换为您要查找的 C++ 类型。

    注意:findChildren() 的相关更改是您需要调用childItems() 而不是children()。理想情况下,QQuickItem 中会有一个模板函数,例如在未来的 Qt 版本中称为 findChildItems(),它在内部执行上述递归搜索。

    【讨论】:

    • +1 谢谢,这非常有效。我认为没有比这更好的方法了。可能这应该是公认的答案...
    【解决方案2】:

    您可以在 C++ 代码中设置模型,而不是解析中继器:

    Parent {
        Rectangle {
            Repeater {
                model: childModel
                delegate: Child {
                     Text { text: childValue }
                }
            }
        }    
    }
    

    在你的 c++ 中:

    QList<QObject*> m_childModel;
    void InitializeChildren() {
        this->m_childModel.append(new Child("value 1"));
        this->m_childModel.append(new Child("value 2"));
        this->m_scene->rootContext()->setContextProperty("childModel", QVariant::fromValue(m_childModel));
    }
    

    您还需要在加载根 QML 文件之前执行setContextProperty

    还有Child 声明:

    class Child : public QObject
    {
        Q_OBJECT
    
    public:
        Child(QString value) : m_value(value) {}
        Q_PROPERTY(QString  childValue    READ getChildValue  WRITE setChildValue    NOTIFY childValueUpdated)
        // Other properties... 
    
        QString getChildValue()    const { return m_value; }
        void setChildValue(const QString &value)
        {
            if (value == m_value)
                return;
            m_value = value;
            emit childValueUpdated();
        }
    
    signals:
        void childValueUpdated();
    
    private:
        QString m_value;
    
    }
    

    【讨论】:

    • 感谢@Kirween 的回答。可能我不是很清楚,但我的目的是在 QML 中而不是在 C++ 中创建一些灵活的结构。附加新的 Child 必须对普通 QML 样式作为嵌套块的用户是透明的。 Child 可以在 Rectangle ot Item 或任何其他 QML 节点内。但是所有这些元素都是 Parent 的孩子,不一定是 Parent 的直接孩子。可能是孩子的孩子......我只需要从这个堆中获取子节点,但它们都是
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    相关资源
    最近更新 更多