Search code examples
javascriptqtqtquickcontrols2

Qt Quick Controls 2 - Changing properties on another page


I have an app that has two pages. The first page of the app is defined in it's own two files: Page1.qml and Page1Form.ui.qml. The second page of the app is also defined in it's own two files: Page2.qml and Page2Form.ui.qml. I'm having trouble understanding how to change the properties of an item that exists on one page in the app using a control from another page.

Let's say I wish to change the text of a Label on Page 1 when a button on Page 2 is pressed. I've already created aliases for both the Label and the Button. For the button's implementation in Page2.qml, I would expect to use the following code:

button.onClicked: {
        Page1Form.label_sourceValue.text = "Text has changed.";
}

However, when pressing the Button while the app is running, I get the error code "TypeError: Type error" with a reference to the line of code where I set the text.

I am new to Qt, so I'm probably just doing something really stupid here...but after 3+ hours of looking on the net for answers, I'm ready to say uncle. Any help would be great.


Solution

  • Each Qt Quick Item can have two ids:

    • The id provided inside the .qml file for the item. This id is not used in this example, e.g. page1thisIdNotUsed and page2thisIdNotUsed.
    • The id given to an Item by its parent. Example page1 and page2 in the example below.

    This example highlights one reason why nobody I know uses the Qt Designer for QML. The Page1.qml file just seems to get in the way and create extra code. In order to access the contents of page1 or page2 from main.qml we would now have to create extra aliases in Page1.qml and Page2.qml.

    Instead, most people prefer to move the contents of Page1Form.ui.qml into Page1.qml. Delete Page1Form.ui.qml, and learn to to QML by hand instead of through the Designer.

    Good luck!

    main.qml

    import QtQuick 2.9
    import QtQuick.Controls 2.2
    import QtQuick.Layouts 1.3
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        SwipeView {
            id: swipeView
            anchors.fill: parent
            currentIndex: tabBar.currentIndex
    
            Page1 {
                id: page1
            }
    
            Page2 {
                id: page2
            }
        }
    
        footer: TabBar {
            id: tabBar
            currentIndex: swipeView.currentIndex
            TabButton {
                text: qsTr("First")
            }
            TabButton {
                text: qsTr("Second")
            }
        }
    }
    

    Page1.qml

    import QtQuick 2.9
    
    Page1Form {
        id: page1thisIdNotUsed
    }
    

    Page1Form.ui.qml

    import QtQuick 2.9
    import QtQuick.Controls 2.2
    
    Item {
        width: 400
        height: 400
    
        property alias label_sourceValue: label
    
        Label {
            id: label
            x: 152
            y: 128
            text: qsTr("Label")
        }
    }
    

    Page2.qml

    import QtQuick 2.4
    
    Page2Form {
        id: page2thisIdNotUsed
        button.onClicked: {
            page1.label_sourceValue.text = "Text has changed.";
        }
    }
    

    Page2Form.ui.qml

    import QtQuick 2.7
    import QtQuick.Controls 2.0
    
    Item {
        property alias button: button
    
        Button {
            id: button
            text: qsTr("Press Me")
        }
    }