如何在QML中访问动态/随机加载的Repeater项?

时间:2013-11-21 02:19:07

标签: qt qml

@TheBootroo在这里提供的答案:link

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

可以使用Repeater :: itemAt(index)方法访问由转发器创建的项目,但由于我不知道项目的加载顺序,我不知道索引screen2,screen3,screen4等等。

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

我的代码如下:

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:

signal changeScreen(string screen)

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

1 个答案:

答案 0 :(得分:4)

  

可以使用Repeater :: itemAt(index)方法访问由转发器创建的项目,但由于我不知道项目的加载顺序,我不知道索引screen2,screen3,screen4等等。

实际定义了Repeater实例化的项目的顺序 - 项目将按模型的顺序实例化,因此在您的情况下,“main”将是第一个,然后是“screen2”,依此类推。现在,Repeater内的每个项目都是一个Loader - Repeater将按照定义的顺序创建3个Loaders。 Loaders自己按需加载源项目。

我认为代码中唯一缺少的是Connections引用Loader,但是你需要它来引用Loader创建的项目。因此,将Connections更改为

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

请注意其他 .item

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

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

更容易将Connections元素放在Repeater的委托中,即有3个Connections而不是1个(假设你有3个屏幕)。