【问题标题】:Page Navigation in QMLQML 中的页面导航
【发布时间】:2019-02-23 03:51:57
【问题描述】:

我正在尝试在 QML 中实现以下 GUI,但无法理解如何正确浏览应用程序的不同页面。

主菜单中有 3 个按钮。当用户单击“演员”按钮时,UI 切换到“演员视图”,用户可以在其中在缩略图视图和列表视图之间切换。当用户点击其中一个演员时,UI 会切换到演员详细信息视图:具有“嵌套在其中”的电影视图的视图,其中列出了所有演员的电影。

我正在尝试使用StackView 来实现它。

因此,当用户单击其中一个按钮时,我的 StackView 位于主菜单屏幕 (main.qml) 中,onClicked 事件会将正确的视图推送到堆栈上。

ActorsView.qml 包含一个内部 StackView(很可能是个坏主意)和 2 个在 Thumb 和 Detail 视图之间切换的按钮。这是通过将 Thumb 或 Detail 视图推送到本地堆栈来完成的。

DetailView.qml 和 ThumbView.qml 功能完全相同,但看起来不同。 这是我遇到麻烦的地方。我希望在 Detail 或 Thumb 视图中发生单击事件时通知主视图。这样它就可以(基于事件传递的信息)知道什么视图推送到主堆栈上。例如,当用户点击 Actor1 时,主菜单可以将“actor 1 的actor detail view”推送到堆栈上。

遗憾的是,我不知道如何“捕捉”在父元素的嵌套组件中触发的事件。

几周前我开始使用 QML 和 QT,很高兴听到我的方法完全错误,并且有更好的方法来实现我想要的。可悲的是,这是迄今为止我发现的唯一可行的选择。

ma​​in.qml

ApplicationWindow {
    title: qsTr("Hello World")
    width: 1280
    height: 720
    visible: true
    id: mainWindow

    Component{
        id: homeScreen
        Rectangle{
            height: 500
            width: 500
            color:"blue"
            anchors.centerIn: mainWindow

            Text {
                anchors.centerIn: parent
                text: qsTr("Home")
                font.pixelSize: 40
            }
        }
    }


    Component{
        id: actorsView
        ActorsView{
            view: stack
        }
    }


    Component{
        id: moviesView
        MoviesView{
            view: stack
        }
    }

    ColumnLayout{
        RowLayout{
            Layout.fillWidth: true


            Button{
                text: "Back"
                onClicked: stack.pop()

            }


            Button{
                text: "actor view"
                onClicked: stack.push(actorView)
            }

            Button{
                text: "movie view"
                onClicked: stack.push(moviesView)

            }

        }

        StackView {
            id: stack
            initialItem: homeScreen
            Layout.fillHeight: true
            Layout.fillWidth: true

        }

    }
}

ActorsView.qml

Item {
    property StackView view

    Component {
        id: actorDetailView
        DetailView {
            name: "actorDetailView"
            text: "Actor"
        }
    }

    Component {
        id: actorThumbView
        ThumbView {
            name: "actorThumbView"
            text: "Actor"
        }
    }

    ColumnLayout {

        RowLayout {

            Text {
                text: "Actor view"
                Layout.fillWidth: true
                horizontalAlignment: Text.AlignHCenter
            }

            Button {
                text: "Detail"
                onClicked: internalStack.push(actorDetailView)
            }
            Button {
                text: "Thumb"
                onClicked: internalStack.push(actorThumbView)
            }

            Button {
                text: "back"
                onClicked: internalStack.pop()
            }

            Button {
                text: "depth: " + internalStack.depth

            }
        }

        StackView {
            id: internalStack
            initialItem: {
                console.log(internalStack.depth)
                internalStack.initialItem = actorThumbView
            }
            Layout.fillHeight: true
            Layout.fillWidth: true
        }
    }
}

ThumbView.qml

Item {
    property string name: "thumbView"
    property string text
    property int counter: 0
    id:thumbView
    signal thumbPressed (string pressedName)

    GridLayout {
        columnSpacing: 10
        rowSpacing: 10
        width: parent.width

        Repeater {
            model: 16
            Rectangle {

                width: 200
                height: 300
                color: "grey"
                Text {
                    id: lable
                    text: text
                    anchors.centerIn: parent
                }

                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        var tag = lable.text
                        console.log("You have clicked " + tag)

                        thumbView.thumbPressed(tag)
                    }
                }

                Component.onCompleted: {
                    counter = counter + 1
                    lable.text = text + " " + counter
                }
            }
        }
    }
}

【问题讨论】:

    标签: qt qml


    【解决方案1】:

    这实际上是构建 QML 应用程序的常用方法,所以不,这并不全是坏事!嵌套 StackViews 是管理页面子内容的强大方法,但肯定会在您的应用程序结构中添加一个级别。通过创建您自己的 Page 项目,重新定义您希望的导航和交互,这变得更加容易。

    在嵌套组件中处理信号有不同的方法。最简单的:在层次结构中向上调用已识别的项目。 QML 中的本地和父元素可以直接从它们的id 访问,即使它们不在同一个 QML 文件中。其中 allowThis 的缺点当然是会导致页面或组件与应用程序的其余部分发生耦合。

    ApplicationWindow {
        id: mainWindow
    
        function pushPage(page) {
            stack.push(page)
        }
        function showActor(id) {
            ...
        }
    
        // ...
    }
    

    在您的页面中...

    MouseArea {
        onClicked: {
            mainWindow.showActor(index)
        }
    }
    

    要实现更模块化的功能,您可以依赖 StackView currentItem、信号、ConnectionsBinding 元素等等,或者在 QML 和/或 C++ 中实现一个接口来管理您的导航。

    根据您的目标架构,肯定有很多可能性,尝试和学习使其完美!

    【讨论】:

    • 谢谢!我正在使用您建议的方法,您在根中声明导航函数并从层次结构中的项目中调用它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 2023-03-09
    • 2013-05-28
    • 1970-01-01
    相关资源
    最近更新 更多