Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Keep the state of the view in a StackView



  • Hello,

    I have a StackView in my App in order to make navigation between different pages.
    It is the first time I use StackView and I'm not sure to understand the complete behaviour.
    Here is a sample of my code/

    The StackView element :

            StackView {
                id: stack
                anchors.fill: parent
                initialItem: 'file:qml/menu.qml'
            }
    

    The function I use to show a page :

    function loadPage(page){
            switch(page){
            case 0 :
                launchPage('menu')
                break
            case 1 :
                launchPage('page1')
                break
            case 2:
                launchPage('page2')
                break
            case 3:
                launchPage('page3')
                break
            }
        }
    
        function launchPage(page){
            return stack.push('file:qml/'+page+'.qml');
        }
    
    

    It behaves quite good except from one detail. When I press a button on my menu it opens the right page. I can use the components of the page but once I go back to menu and come back to my page I've lost my actions on the components.

    For example if my page1 has a Textinput : When I go on page1 and change the value of the TextInput then go to menu and come back to page1 my TextInput has been reset.

    I thought it would be reset only if I pop() my page but obviously not.
    What should I do to keep my changes on the page ?
    Maybe each time I press the menu button it open a new instance of page1 ?


  • Moderators

    hi @DavidM29 ,

    As far as I know, that is indeed what happens here.

    with return stack.push('file:qml/'+page+'.qml'); you tell the stackview to create a new Item from that qml file and show it.

    I believe if you have the components as actual items/instances in your main qml, than it should work like you thought it would.

    something like this (taken from the docs):

    StackView {
        id: stack
        initialItem: view
    
        Component {
            id: view
    
            MouseArea {
                Text {
                    text: stack.depth
                    anchors.centerIn: parent
                }
                onClicked: stack.push(view)
            }
        }
    }
    

  • Moderators

    @DavidM29 said in Keep the state of the view in a StackView:

    For example if my page1 has a Textinput : When I go on page1 and change the value of the TextInput then go to menu and come back to page1 my TextInput has been reset.

    Thats also i would expect, but u didn't show how you "go back" again.

    Is it correct that a page can launch a menu? If so everytime a new menu page is pushed into the stack view? is that correct?



  • I go back on the menu by calling launchPage(0) on press of a button, which call a dedicated .qml file (a window with a few buttons).
    So from what you told me when I "push()" a page it load a new instance of this one. Wich is not what I want to do. How Am I supposed to handle this ?
    I'm obliged to create an instance of each page but don't wan't more. I just want to switch from one to another. Just like setCurrentIndex(x) behave in a QStackWidget in a standart Qt UI.


  • Moderators

    @DavidM29
    the QML stackview behaves a bit different here than the C++ stackkview.

    Why not simply create all 4 pages, anchor them to the same parent. and bind their visibility to a page property: visible: page === someItem.currentPage. Then simply switch pages by assigning the page index to someItem.currentPage

    Alternatively you could also create a ListView element with a ObjectModel:

    ListView {
         id: list
         snapMode: ListView.SnapOneItem
         currentIndex: ... // the page to show
         interactive: false
    
         ObjectModel {
             Item { height: list.height; width: list.width }
             Item { height: list.height; width: list.width }
             Item { height: list.height; width: list.width }
         }
    }
    

    adapt some more properties of the ListView like disabling scrolling etc



  • Yes that's probably the reason why I'm confused here.

    I'm going to try your solution. It could works fine.



  • @raven-worx
    Finally I used your first solution here is a sample of the code I used :

    main.qml

            Menu{
                id:p0
                visible: true
            }
    
            Page1{
                id: p1
                visible: false
            }
    
            Page2{
                id: p2
                visible: false
            }
        }
    
        function loadPage(page){
            resetPages()
            switch(page){
            case 0 :
                p0.visible=true
                break
            case 1 :
                p1.visible=true
                break
            case 2:
                p2.visible=true
                break
            }
        }
    
        function resetPages(){
            p0.visible=false
            p1.visible=false
            p2.visible=false
        }
    

    This works fine. If you see any improvements I can make please tell me.


Log in to reply