Qml 中的“递归实例化错误”有解决方法吗?

问题描述 投票:0回答:1

我有一种情况,我需要一个包含自己类型的 ListView 的组件。这是一个简化版本:

myComp.qml

import QtQuick

Item {
    Text {
        id: name
        text: qsTr("Hello")
    }

    ListView{
        model: 5
        delegate: MyComp{}
    }
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    MyComp{

    }
}

qmldir.txt

MyComp 1.0 myComp.qml

运行此命令后,我得到了预期的

recursive instantiation error

我的主要问题是:

  • 有解决方法可以解决这个问题吗?
  • 如果你想实现这样的事情,一般的方法是什么?例如,如果我想实现类似于here提供的查询生成器 UI 之类的功能,我该怎么办?
qt recursion qml instantiation qt6
1个回答
0
投票

正如 @Atmo 在评论中提到的,您不能自行声明类型。但是,在您的情况下,不会发生无限循环。

据我所知,有两种选择可以解决您的问题:

  1. 使用 Loader 项目,如 [1] 中所述。
  2. 在组件声明期间设置委托。

1.装载机

最简单的选择是使用加载器 [1]。我还建议使用 DelegateChooser 在委托之间切换,因为您不需要在所有子项和写入条件等上使用 Loader

例如:

组.qml

import QtQuick
import QtQuick.Controls
import Qt.labs.qmlmodels

Control {
    id: control

    property alias model: listview.model
    padding: 5

    DelegateChooser {
        id: chooser
        role: 'type'

        DelegateChoice {
            roleValue: 'data'
            Control {
                required property var modelData
                padding: 5

                contentItem: Row {
                    spacing: 5

                    Repeater {
                        model: modelData.data
                        Label {
                            required property string modelData
                            padding: 5
                            width: 35
                            text: modelData
                            background: Rectangle {
                                radius: 2; border { width: 1; color: '#ccc'}
                            }
                        }
                    }
                }

                background: Rectangle {
                    radius: 5
                    border { width: 1; color: '#eee'}
                }
            }
        }

        DelegateChoice {
            roleValue: 'group'
            Loader {
                required property var modelData
                source: 'Group.qml'
                width: control.availableWidth
                onLoaded: item.model = modelData.data
            }
        }
    }

    contentItem: ListView {
        id: listview
        implicitHeight: contentHeight
        spacing: 5
        delegate: chooser
    }

    background: Rectangle {
        color: '#aafbf3dd'
        radius: 5; border { width: 1; color: '#dcc896'}
    }
}

用法如下:

Group {
    anchors.fill: parent
    model: [
        {type: 'data', data: [1,2,3]},
        {
            type: 'group',
            data: [
                {type: 'data', data: [4,5,6,7]},
                {type: 'data', data: [8,9,10,11]},
                {type: 'group', data: [{type: 'data', data: [12,13,14]}]},
            ]
        },
    ]
}

预览

2.将委托移至文件外部

这是一种更干净的方法,因为它不需要 Loader,但它确实需要使用多个文件,这很好。这是一个简化的示例:

组.qml

import QtQuick
import QtQuick.Controls

Control {
    id: control

    property alias model: listview.model
    padding: 5

    property Component delegate: Item {}

    contentItem: ListView {
        id: listview
        spacing: 5

        implicitHeight: contentHeight
        delegate: control.delegate
    }

    background: Rectangle {
        color: '#aafbf3dd'
        radius: 5; border { width: 1; color: '#dcc896'}
    }
}

Delegate.qml(简化版)

import QtQuick
import QtQuick.Controls
import Qt.labs.qmlmodels

DelegateChooser {
    id: chooser
    role: 'type'

    DelegateChoice {
        roleValue: 'data'
        Row {
            required property var modelData
            spacing: 5
            Repeater {
                model: modelData.data
                Label {
                    required property string modelData
                    text: modelData
                }
            }
        }
    }

    DelegateChoice {
        roleValue: 'group'
        Group {
            required property var modelData
            width: ListView.view.parent.width - 10
            model: modelData.data
            delegate: chooser
        }
    }
}

用法保持不变:

Group {
    anchors.fill: parent
    model: [ /* same data */ ]
    delegate: Delegate {}
}

预览

© www.soinside.com 2019 - 2024. All rights reserved.