我有一个包含嵌套 StackView 的 QML 代码。我正在尝试建立一个动态且自动的“路径”系统,该系统将在屏幕顶部显示到达当前视图(包括子 StackView)的路径。例如,使用以下代码,我们将看到显示:
Path: Home > Module 1 > Sub-Module 3 > Data Page
。
理想情况下,我还希望单击路径中的名称可以将我们带到该页面,此外还有一个可向后导航一页的后退按钮。因此,将
objectName
属性添加到动态更新列表的解决方案并不是真正可行,因为它不太灵活。
这是我当前的代码,其中路径仅适用于第一个 StackView。我怎样才能添加这个功能?
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ApplicationWindow {
visible: true
width: 800
height: 600
title: "StackView With Dynamic Path"
ColumnLayout {
anchors.fill: parent
RowLayout {
id: pathBar
spacing: 5
Layout.fillWidth: true
Text {
text: "Path :"
font.bold: true
}
Repeater {
model: stackPath
Row {
spacing: 5
Text {
text: modelData
}
Text {
visible: index < stackPath.count - 1
text: ">"
}
}
}
}
// StackView principal
StackView {
id: mainStackView
Layout.fillWidth: true
Layout.fillHeight: true
initialItem: homeComponent
clip: true
Component {
id: homeComponent
Page {
objectName: "Home"
Rectangle {
color: "lightblue"
anchors.fill: parent
Text {
anchors.centerIn: parent
text: "Homepage"
}
Button {
text: "Go to Module 1"
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
onClicked: mainStackView.push(module1Component)
}
}
}
}
Component {
id: module1Component
Page {
objectName: "Module 1"
StackView {
id: module1StackView
anchors.fill: parent
initialItem: subModuleComponent
Connections {
target: module1StackView
onCurrentItemChanged: updatePath()
onPush: updatePath()
onPop: updatePath()
}
Component {
id: subModuleComponent
Page {
objectName: "Sub-Module 3"
Rectangle {
color: "lightgreen"
anchors.fill: parent
Text {
anchors.centerIn: parent
text: "Sub-Module 3"
}
Button {
text: "Go to Data Page"
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
onClicked: module1StackView.push(dataPageComponent)
}
Button {
text: "Back"
anchors.bottom: parent.bottom
anchors.left: parent.left
onClicked: module1StackView.pop()
}
}
}
}
Component {
id: dataPageComponent
Page {
objectName: "Data Page"
Rectangle {
color: "lightcoral"
anchors.fill: parent
Text {
anchors.centerIn: parent
text: "Data Page"
}
Button {
text: "Back"
anchors.bottom: parent.bottom
anchors.left: parent.left
onClicked: module1StackView.pop()
}
}
}
}
}
Button {
text: "Back"
anchors.bottom: parent.bottom
anchors.left: parent.left
onClicked: mainStackView.pop()
}
}
}
}
}
ListModel {
id: stackPath
}
function updatePath() {
stackPath.clear()
buildPath(mainStackView, "")
}
function buildPath(stackView, currentPath) {
for (var i = 0; i < stackView.depth; i++) {
var currentItem = stackView.get(i)
currentPath += currentItem.objectName
stackPath.append({ name: currentItem.objectName })
var childStackView = currentItem.children.find(function(item) {
return item instanceof StackView
})
if (childStackView && childStackView.currentItem) {
buildPath(childStackView, currentPath + " > ")
}
}
}
Connections {
target: mainStackView
onCurrentItemChanged: updatePath()
onPush: updatePath()
onPop: updatePath()
}
Component.onCompleted: updatePath()
}
似乎你有一个可行的解决方案,但是,我认为我们可以用一个标签来做到这一点。以下内容有效,因为从推送/弹出操作对
stackView.depth
的更改将导致重新评估文本属性。另外,您使用 objectName,我建议您改用 Page.title :
Label {
text: {
let titles = [ ];
for (let i = 0; i < stackView.depth; i++)
titles.push(stackView.get(i).title);
return titles.join( " > " );
}
}
您可以在线尝试!