Search code examples
c++qtqmlqt5qbuttongroup

Qt5 - QML: Button does not show up after triggered


I am writing a project that is using Qt5-QML. In order to shrink the problem I prepared a small example that replicates the problem.

1) I have an application on a Page1. That carries a Button as shown in the below print screen below:

launch

2) After the user pushes the button goes on Page2 shown below which carries different Buttons. Let's say Button A it is the user's choice:

buttons

3) The final screen represented by Page1 is the correct choice, which is the the button selected

correct-selection

The problem I have is that after the user selects the choice on point 2) and goes back on Page1 a Button should appear on Page1 in the middle of the Page1 that opens a dialog window, in my case a WebEngineView only related to that Button. Of course if the user selcts Button 3 on Page2, back on Page1 there should be another Button that opens another dialog related to Button 3 and that is always a WebEngineView.

I can't see the Button and the related dialog.

The expected result is the print screen below:

Below the snippet of code that carries the problem:

main.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Conn")
    property Page1 page1: Page1 {}
    property Page2 page2: Page2 {}
    Component.onCompleted: {
        page2.onButtonClicked.connect(function(buttonId, buttonName) {
            page1.mytext.text = buttonId;
            page1.mytext.text = buttonName;
            mystackview.pop();
        });
    }

// These buttons should appear only after the user selects the choices on `Page2` 
    Button {
        id: dialogA
        Layout.fillWidth: true
        text: "Open Dialog A"
    }
    Button {
        id: dialogB
        Layout.fillWidth: true
        text: "Open Dialog B"
    }
    Button {
        id: dialogC
        Layout.fillWidth: true
        text: "Open Dialog C"
    }

    StackView {
        id: mystackview
        anchors.fill: parent
        initialItem: page1
    }
}

page1.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
Page {
    property alias mytext: mytext
    Button {
        id: button1
        text: "Select"
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top
        onClicked: {
            mystackview.push(page2);
        }
    }
    Text {
        id: mytext
        anchors.top: button1.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        font.bold: true
        font.pointSize: 30
    }
}

page2.qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

Page {
    signal onButtonClicked(var buttonId, var buttonName)

    Component.onCompleted: {
        button1.clicked.connect(function() {
            onButtonClicked(1, "A");
        });
        button2.clicked.connect(function() {
            onButtonClicked(2, "B");
        });
        button3.clicked.connect(function() {
            onButtonClicked(3, "C");
        });
    }

    ColumnLayout {
        id: mybuttons
        anchors.fill: parent
        spacing: 5
        Button {
            id: button1
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "A"
        }
        Button {
            id: button2
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "B"
        }
        Button {
            id: button3
            Layout.fillWidth: true
            Layout.fillHeight: true
            text: "C"
        }
    }

What I tried so far:

1) I came across the following source which was useful to understand the style of a component. And that is for this reason that I used Component.onCompleted: on my code. Which did a good job in triggering the buttons at Page2. I thought that I could use the same philosophy also for the others but they are not showing up.

2) This source was useful for me to understand the properties of a components, in particular in the example how to highlight on a click. I think this is the most close that I can find for what I am doing.

3) Digging more in what I am trying to achieve I went ahead and went through the official documentation which seems to push for the use of the property onCurrentItemChanged which could be a choice as triggers the emit properties of a signal.

UPDATES

The following part in the main.qml is used to show that once the user triggers one of the three buttons, then on page1 it is shown the letter of the Button that was clicked, in fact it is possible to see it on point 3) of the procedure.

Component.onCompleted: {
        page2.onButtonClicked.connect(function(buttonId, buttonName) {
            page1.mytext.text = buttonId;
            page1.mytext.text = buttonName;
            mystackview.pop();
        });

This is connected to the signal on the page2.qml as shown below:

signal onButtonClicked(var buttonId, var buttonName)

Why I can't see the Button after I go back on Page1 of my QML application? Thank you very much for pointing in the right direction to solve this problem.


Solution

  • As mentioned in my comment, the "Open Dialog" buttons are always hidden by the stack view anyway. If they weren't hidden by that, they'd in any case need some flag to indicate whether they should be visible or not, based on the selection made on Page2.

    Keeping with the existing structure of your MRE, here's one way it could work. I've moved the "Open Dialog" buttons to Page1 because that seems to make the most sense, but they could also be on some separate page, or incorporated into main.qml if there were some layout there which allowed that. Also I made a signal/slot connection from Page1 to trigger the Page2 load in main.qml (instead of directly trying to access objects in main.qml, which is bad practice). I also removed the text label from Page1 to simplify the code. Page2 code remains unchanged so I do not include it.

    main.qml

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Conn")
        property Page1 page1: Page1 {}
        property Page2 page2: Page2 {}
    
        Component.onCompleted: {
            page1.selectDialog.connect(function()  {
                mystackview.push(page2);
            });
    
            page2.onButtonClicked.connect(function(buttonId, buttonName) {
                page1.dialogId = buttonId;
                mystackview.pop();
            });
        }
    
        StackView {
            id: mystackview
            anchors.fill: parent
            initialItem: page1
        }
    }
    

    Page1.qml

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Layouts 1.12
    
    Page {
    
        property int dialogId: -1;
    
        signal selectDialog()
    
        ColumnLayout {
            anchors.fill: parent
            spacing: 5
    
            Button {
                id: button1
                text: "Select"
                onClicked: selectDialog()
                Layout.fillWidth: true
            }
    
            // These buttons should appear only after the user selects the choices on `Page2`
            Button {
                id: dialogA
                text: "Open Dialog A"
                visible: dialogId === 1
                Layout.fillWidth: true
            }
            Button {
                id: dialogB
                text: "Open Dialog B"
                visible: dialogId === 2
                Layout.fillWidth: true
            }
            Button {
                id: dialogC
                text: "Open Dialog C"
                visible: dialogId === 3
                Layout.fillWidth: true
            }
        }
    }
    

    enter image description here enter image description here enter image description here