[Solved] QML Back Button with JavaScript or ListModel?



  • This seems like it should be simple but I haven't been able to get it done yet. I have a back button that shows up on every page except for the home page and I just want it to store the name of the last page visited and then navigate there when the user taps the back button. I have been using page loaders to navigate:

    Main.qml

    @import Qt 4.7

    Rectangle {
    width: 640
    height: 480

    function changePage(newPage)
    {
        pageLoader.source = newPage;
        console.log(newPage)
    }
    
    Loader {
        id: pageLoader
        z: 1
        source: "1.qml"
    }
    
    Connections {
        target: pageLoader.item
        onPageRequested: changePage(page)
    }
    

    }
    @

    And then in each page I use:

    @ signal pageRequested(string page)

    MouseArea {
       ....
        onClicked: pageRequested("2.qml")@
    

    to navigate around my pages. Obviously the 2.qml gets replaced for whatever page I am going to.

    Any help would be appreciated.

    Thanks,

    Kyle



  • Well I think you need some sort of list to map the qml files to numbers (1,2,…).
    Then have a list that stores history. Every time there is a page change, append the new index.
    Then when they press back, go to last element in history and delete last one too ( put it in forward history if you want).

    You can use ListModel or similar in qml or implement in c++ if you're more comfortable.



  • I agree with the concept, I am just not sure how to make, store, and edit the list you referenced.



  • Try using a ListModel with elements 'index' and 'filename'. You can use model.get(index).filename to map.



  • I am trying to tackle this back button. This is how I began but I don't think this is the right direction. Your feedback would be appreciated:

    @import Qt 4.7

    Rectangle {
    width: 640
    height: 480

    function changePage(newPage)
    {
        pageLoader.source = newPage;
    
        newPage = backbuttonmap.get(index).filename;
    
        //Used for logging a page change, creates a verbose console window
        //console.log(newPage)
    }
    
    ListView {
         model: BackButtonModel { id: backbuttonmap }
    
    
    Loader {
        id: pageLoader
        z: 1
        source: "1.qml"
    }
    
    Connections {
        target: pageLoader.item
        onPageRequested: changePage(page)
    }
    

    }
    }@

    My model:

    @import Qt 4.7

    ListModel {
    ListElement {
    index: 1
    filename: "1.qml"
    }
    ListElement {
    index: 2
    filename: "2.qml"
    }
    ListElement {
    index: 3
    filename: "3.qml"
    }
    ListElement {
    index: 4
    filename: "4.qml"
    }
    ListElement {
    index: 5
    filename: "5.qml"
    }
    ListElement {
    index: 6
    filename: "6.qml"
    }
    ListElement {
    index: 7
    filename: "7.qml"
    }
    ListElement {
    index: 8
    filename: "8.qml"
    }
    ListElement {
    index: 9
    filename: "9.qml"
    }
    ListElement {
    index: 10
    filename: "10.qml"
    }

    }
    @

    And here is an example page:

    @import Qt 4.7

    Rectangle {
    id: screen
    width: 640
    height: 480
    color: "#086421"
    signal pageRequested(string page)

    Rectangle {
        id: rectangle1
        x: 1
        y: 0
        width: 557
        height: 95
        gradient: Gradient {
            GradientStop {
                position: 0
                color: "#b36c67"
            }
    
            GradientStop {
                position: 0.21
                color: "#661d17"
            }
        }
        border.width: 0
        border.color: "#086421"
    
    
        MenuTitle {
            id: menutitle1
            x: 0
            y: 0
            title: "Sound Settings"
        }
    }
    
    TabMenu {
        id: tabmenu1
        x: 0
        y: 48
        state: "State2"
        onPageRequested: screen.pageRequested(page)
    }
    
    SetupBars {
        id: setupbars1
        x: 558
        y: 0
    }
    

    }

    @



  • I tried implementing with JavaScript but I couldn't get it to work. Any ideas would be appreciated.

    @ var count = 0;
    var stack = [];
    var lastpage;

    function changePage(newPage)
    {

        pageLoader.source = newPage;
        stack.push(newPage);
        count = count + 1;
    
    
    }
    

    function lastPage()
    {

    lastpage = stack.pop(count);

    }
    @

    For my back button the code is:

    @MouseArea {
    id: mouse_area_back
    x: 0
    y: 381
    width: 82
    height: 99
    onClicked: {
    console.log(PageChange);
    pageRequested(PageChange.lastpage);
    }
    }@

    and my main page:

    @import Qt 4.7
    import "pageChanger.js" as PageChange

    Rectangle {
    width: 640
    height: 480

    function changePage(newPage) { PageChange.changePage(newPage) }

    Loader {
        id: pageLoader
        z: 1
        source: "1.qml"
    }
    
    Connections {
        target: pageLoader.item
        onPageRequested: changePage(page)
    }
    

    }

    @



  • You're almost there (with the first one you had).
    Don't worry about the javascript, you can do it in the QML (which really is javascript anyway).

    The only thing you're missing is the page stack. Where is the page variable? And why is it a string? If you are putting the filename (eg. 1.qml) then you don't need the model.



  • You will have to excuse my ignorance again but how do I implement a page stack in qml?



  • Like you were trying to do in the javascript.
    Make a List with previous pages you have accessed.

    I don't think you are showing all the code? When you change page (purposefully), you need to append that page to the 'stack' -- your history (like the javascript code does).
    Then, when you use the back button, simply change to the last item on your page stack. Then remove that item.



  • I like the concept but I am weak on the qml code.



  • I'm weak on interpreted code, more a C++ guy, but QML seems the same as Javascript (at least syntax-wise).

    If you can provide me with a minimal code base that needs this 'back button' functionality, I can add it on for you. No need to give me all the pages, just two or three will do.



  • These are my pages as they stand, javascript still there from attempt 1.

    My Main.qml:

    @import Qt 4.7
    import "pageChanger.js" as PageChange

    Rectangle {
    width: 640
    height: 480

    function changePage(newPage) { PageChange.changePage(newPage) }

    Loader {
        id: pageLoader
        z: 1
        source: "1.qml"
    }
    
    Connections {
        target: pageLoader.item
        onPageRequested: changePage(page)
    }
    

    }

    @

    PageChanger.js

    @ var count = 0;
    var stack = ["1.qml"];
    var visited;

    function changePage(newPage)
    {

        pageLoader.source = newPage;
        stack.push(pageLoader.source);
        count = count + 1;
        console.log(count)
    
    }
    

    function lastPage()
    {

    console.log("in function")
    console.log(stack);
    

    // stack.pop();
    stack.pop();
    console.log(stack);
    pageRequested(stack);

    }
    @

    A Sample Page:

    @import Qt 4.7

    Rectangle {
    id: screen
    width: 640
    height: 480
    color: "#086421"
    signal pageRequested(string page)

    Rectangle {
        id: rectangle1
        x: 1
        y: 0
        width: 557
        height: 95
        gradient: Gradient {
            GradientStop {
                position: 0
                color: "#b36c67"
            }
    
            GradientStop {
                position: 0.21
                color: "#661d17"
            }
        }
        border.width: 0
        border.color: "#086421"
    
    
        MenuTitle {
            id: menutitle1
            x: 0
            y: 0
            title: "Screen Brightness"
        }
    }
    
    TabMenu {
        id: tabmenu1
        x: 0
        y: 48
        state: "State2"
        onPageRequested: screen.pageRequested(page)
    }
    
    SetupBars {
        id: setupbars1
        x: 558
        y: 0
    }
    

    }

    @

    Setup Bars code:

    @import Qt 4.7
    import "pageChanger.js" as PageChange

    Rectangle {
    width: 82
    height: 480

    SetupBlack {
        id: setupblack1
        x: 1
        y: 383
    }
    
    SetupBlack {
        id: setupblack2
        x: 1
        y: 287
    }
    
    SetupBlack {
        id: setupblack3
        x: 1
        y: 191
    }
    
    SetupBlack {
        id: setupblack4
        x: 1
        y: 95
        smooth: true //test
    }
    
    SetupBlack {
        id: setupblack5
        x: 1
        y: -1
    }
    
    Text {
        id: text1
        x: 15
        y: 36
        width: 80
        height: 20
        color: "#ffffff"
        text: "Home"
        font.pixelSize: 19
        font.family: "Arial"
        font.bold: true
    }
    
    Image {
        id: image1
        x: 5
        y: 395
        width: 73
        height: 50
        source: "Images/back.png"
    }
    
    Text {
        id: text2
        x: 18
        y: 440
        width: 80
        height: 20
        color: "#ffffff"
        text: "Back"
        font.bold: true
        font.family: "Arial"
        font.pixelSize: 19
    }
    
    MouseArea {
        id: mouse_area1
        x: 0
        y: -2
        width: 82
        height: 97
        onClicked: pageRequested("1.qml")
    }
    
    MouseArea {
        id: mouse_area_back
        x: 0
        y: 381
        width: 82
        height: 99
        onClicked: PageChange.lastPage();
        }
    

    }
    @



  • One of the more important parts is 'TabMenu'. I guess it has all the pages on it?
    I will try to implement some buttons there.



  • I really had to cut that up to get it to fit within the 6000 character limit but hopefully the bulk of what matters is there.



  • It's alright, I don't need the TabMenu. I just made some buttons. So deleted that huge post :)

    I have finished the back button. Here it is:

    Main.qml
    @iimport QtQuick 1.0
    Rectangle {
    width: 640; height: 480
    ListModel {
    id: pageModel
    function pageRequested(page)
    {
    append({"page": pageLoader.source})
    pageLoader.source = page
    }
    function pageLast()
    {
    pageLoader.source = get(count - 1).page
    remove(count - 1)
    }
    }
    Loader {
    id: pageLoader
    anchors.left: parent.left
    source: "home.qml"
    }
    SetupBars {
    anchors.right: parent.right
    width: 80
    }
    }@

    PageButton.qml
    @import QtQuick 1.0

    Rectangle {
    property alias text: status.text
    property string file
    width: 100; height: 30
    border.width: 3
    border.color: "#086421"
    Text { id: status; anchors.centerIn: parent }
    MouseArea { anchors.fill: parent; onClicked: pageModel.pageRequested(file) }
    }@

    Home.qml
    @import QtQuick 1.0

    Rectangle {
    id: screen
    width: 560; height: 480
    color: "#A834F1"
    Text {
    text: "Welcome Home!"
    anchors.centerIn: parent
    }
    Rectangle {
    id: rectangle1
    width: parent.width
    height: 95
    gradient: Gradient {
    GradientStop { position: 0; color: "#b36c67" }
    GradientStop { position: 0.21; color: "#661d17" }
    }
    PageButton {
    x: 50; y: 50
    text: "Bluetooth"
    file: "1.qml"
    }
    PageButton {
    x: 200; y: 50
    text: "Screen Brightness"
    file: "2.qml"
    }
    }
    }@

    1.qml
    @import QtQuick 1.0

    Rectangle {
    id: screen
    width: 560; height: 480
    color: "#086421"
    Text {
    text: "Bluetooth!"
    anchors.centerIn: parent
    }
    Rectangle {
    id: rectangle1
    width: parent.width
    height: 95
    gradient: Gradient {
    GradientStop { position: 0; color: "#b36c67" }
    GradientStop { position: 0.21; color: "#661d17" }
    }
    PageButton {
    x: 50; y: 50
    text: "Screen Brightness"
    file: "2.qml"
    }
    }
    }@

    2.qml
    @import QtQuick 1.0

    Rectangle {
    id: screen
    width: 560; height: 480
    color: "#9864F1"
    Text {
    text: "Screen Brightness"
    anchors.centerIn: parent
    }
    Rectangle {
    id: rectangle1
    width: parent.width
    height: 95
    gradient: Gradient {
    GradientStop { position: 0; color: "#b36c67" }
    GradientStop { position: 0.21; color: "#661d17" }
    }
    PageButton {
    x: 50; y: 50
    text: "Bluetooth"
    file: "1.qml"
    }
    }
    }@

    SetupBars.qml
    @import QtQuick 1.0

    Rectangle {
    id: screen
    width: 80; height: 480
    color: "black"
    Text {
    id: text1
    x: 15; y: 36
    width: 80; height: 20
    color: "white"
    text: "Home"
    font.pixelSize: 19
    font.family: "Arial"
    font.bold: true
    MouseArea {
    anchors.fill: parent
    onClicked: pageModel.pageRequested("home.qml")
    }
    }
    Item {
    anchors.bottom: parent.bottom;
    width: 80; height: 50
    visible: pageModel.count > 0
    Image {
    anchors.left: parent.left
    source: "Images/back.png"
    }
    Text {
    anchors.right: parent.right
    color: "white"
    text: "Back"
    font.bold: true
    font.family: "Arial"
    font.pixelSize: 19
    }
    MouseArea {
    anchors.fill: parent
    onClicked: pageModel.pageLast();
    }
    }
    }@



  • Thanks so much for your help.



  • Just a note: I got it to work only when I put "pageLoader.source = get(count - 2).page" and not "pageLoader.source = get(count - 1).page"



  • You must have added something to the list.
    As count is indexed starting with 1 while the array is indexed starting with 0, you use count-1 to map to the array. Hence, count-1 retrieves the last element in the array. Your version will get the second last element in the array, so something odd there.

    The one I posted works perfectly though (without adding any additional code) :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.