@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")
}
}
答案 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个屏幕)。