如何访问 QML 中动态/随机加载的中继器项目? [英] How to access dynamically/randomly loaded Repeater items in QML?

查看:14
本文介绍了如何访问 QML 中动态/随机加载的中继器项目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@TheBootro 在此处提供的答案:link

The answer provided by @TheBootroo here: link

提供了一种在 QML 文件/屏幕/视图之间加载和更改的方法.但是当这样做时,如何使用信号和插槽?

provides a way to load and change between QML files/screens/views. But when doing it like this how can one use signal and slots?

可以使用 Repeater::itemAt(index) 方法访问中继器创建的项目,但由于我不知道项目的加载顺序,所以我不知道 screen2、screen3、screen4 的索引是什么等等.

One can access the items created by the repeater by using the Repeater::itemAt(index) method, but since I don't know in what order the items are loaded I don't know what index screen2, screen3, screen4 etc. is at.

有什么办法可以解决这个问题,还是必须在启动时实例化内存中的所有屏幕?

Is there any way to solve this or do one have to instantiate all the screens in memory at start up?

我的代码如下:

main.qml:

//List of screens
    property variant screenList: [
        "main",
        "screen2",
        "screen3",
        ...
    ]

    //Set this to change screen
    property string currentScreen: "main"


    Repeater {
        id: screens
        model: screenList
        delegate: Loader {
            active: false;
            asynchronous: true
            anchors.fill:  parent
            source: "%1.qml".arg(modelData)
            visible: (currentScreen === modelData)
            onVisibleChanged: {
                loadIfNotLoaded()
            }
            Component.onCompleted: {
                loadIfNotLoaded()
            }

            function loadIfNotLoaded () {
                //To load start screen
                if(visible && !active) {
                    active = true;
                }
            }
        }
    }

    Connections {
        target: screens.itemAt(indexHere)
        //screen is here the string passed with the signal from screen2.
        onChangeScreen: currentScreen = screen
    }

    Button {
        id: button1
        text: "Go To Screen 2"
        onClicked: {
            currentScreen = "screen2"
        }
    }

在screen2.qml中:

And in screen2.qml:

signal changeScreen(string screen)

Button {
    text: "Go To Main"
    onClicked: {
        changeScreen("main")
    }
}

推荐答案

可以使用 Repeater::itemAt(index) 方法访问中继器创建的项目,但由于我不知道项目的加载顺序,所以我不知道 screen2、screen3、screen4 的索引是什么等等.

One can access the items created by the repeater by using the Repeater::itemAt(index) method, but since I don't know in what order the items are loaded I don't know what index screen2, screen3, screen4 etc. is at.

Repeater 实例化的项目的顺序实际上是定义的 - 这些项目将按照模型的顺序实例化,因此在您的情况下,main"将是第一个,然后是screen2",依此类推.现在,Repeater 中的每个项目都是一个 Loader——Repeater 将按照定义的顺序创建 3 个 Loader.加载器自己按需加载源项目.

The order of the items the Repeater instantiates is actually defined - the items will be instantiated in the order of the model, so in your case "main" will be the first, then "screen2" and so on. Now, each item inside of the Repeater is a Loader - the Repeater will create 3 Loaders in a defined order. The Loaders themselves load their source item on demand.

我认为您的代码中唯一缺少的是 Connections 引用了 Loader,但您需要它来引用 Loader 创建的项目.所以将连接更改为

I think the only thing missing in your code is that the Connections refers to the Loader, but you need it to refer to the item the Loader creates. So change the Connections to

Connections {
    target: screens.itemAt(indexHere).item
    onChangeScreen: currentScreen = screen
}

注意额外的.item.

修复此问题后,还有一个额外的问题:在创建 Connections 元素时,Repeater 尚未实例化其项目,因此 screens.itemAt(indexHere) 将返回 null.解决此问题的一种方法是使用 currentIndex 属性而不是 currentScreen 属性并在 target 的绑定中使用它,然后设置 <在Repeater实例化其项目之后的code>currentIndex:

After fixing this, there is one additional problem though: The Repeater hasn't yet instantiated its items when the Connections element is created, so screens.itemAt(indexHere) will return null. One way to fix this would be to use a currentIndex property instead of a currentScreen property and use that in the binding for target, and set currentIndex after the Repeater has instantiated its items:

property int currentIndex: -1
...
Connections {
    target: screens.itemAt(currentIndex).item
    ...
}
Component.onCompleted: currentIndex = 0

更简单的方法可能是将 Connections 元素放在中继器的委托中,即有 3 个连接而不是一个(假设您有 3 个屏幕).

Even easier would probably be to put the Connections element inside the Repeater's delegate, i.e. have 3 Connections instead of one (assuming you have 3 screens).

这篇关于如何访问 QML 中动态/随机加载的中继器项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆