【问题标题】:Qt5 - QML: Button does not show up after triggeredQt5 - QML:触发后按钮不显示
【发布时间】:2020-03-15 12:34:11
【问题描述】:

我正在编写一个使用Qt5-QML 的项目。为了缩小问题,我准备了一个复制问题的小例子。

1) 我有一个Page1 上的应用程序。带有Button,如下面的打印屏幕所示:

2) 用户按下按钮后,Page2 如下图所示,带有不同的Buttons。假设Button A是用户的选择:

3)Page1代表的最终画面是正确的选择,也就是被选中的按钮

问题我的问题是,在用户选择第 2 点的选项并返回 Page1 后,Button 应该出现在 Page1 中间的 @987654337 @ 打开一个对话框窗口,在我的例子中是一个 WebEngineView 只与那个 Button 相关。 当然,如果用户在Page2 上选择Button 3,则返回Page1 应该有另一个Button 打开另一个与Button 3 相关的对话框,并且始终是WebEngineView

我看不到Button 和相关对话框。

预期的结果是下面的打印屏幕:

在带有问题的代码的sn-p下面:

ma​​in.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"
        }
    }

到目前为止我尝试了什么

1) 我遇到了以下source,它有助于理解组件的style。这就是我在代码中使用Component.onCompleted: 的原因。在触发Page2 的按钮方面做得很好。我认为我也可以对其他人使用相同的理念,但他们没有出现。

2) This source 对我了解组件的属性很有用,特别是在示例中如何突出显示单击时。我认为这是我能找到的最接近我正在做的事情。

3) 深入挖掘我想要实现的目标,我继续阅读官方文档,该文档似乎在推动使用属性 onCurrentItemChanged,这可能是触发 emit 属性的一个选择信号。

更新

ma​​in.qml 中的以下部分用于显示一旦用户触发三个按钮之一,然后在page1 上显示Button 的字母点击,实际上可以在程序的 3) 点看到它。

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

这是连接到page2.qml上的signal,如下图:

signal onButtonClicked(var buttonId, var buttonName)

为什么我在我的QML 应用程序中返回Page1 后看不到Button? 非常感谢您指出解决此问题的正确方向。

【问题讨论】:

  • 为什么是page1.mytext.text = buttonId; page1.mytext.text = buttonName;
  • 我只是检查是否按下了正确的按钮,实际上我是在获取在page2 触发的按钮的 id 和名称并将其显示在page1 上作为双重检查。
  • 据了解,MRE 不应包含这些元素,因为它们是干扰分析的噪音。你不觉得引入这种噪音是不必要的吗?
  • “buttonId”和“buttonName”变量提供什么信息?
  • 我认为person类的代码是不必要的,因为说“这个代码对我有用”根本没有帮助。

标签: c++ qt qml qt5 qbuttongroup


【解决方案1】:

正如我在评论中提到的,“打开对话框”按钮总是被堆栈视图隐藏。如果他们没有被隐藏,他们无论如何都需要一些标志来指示他们是否应该可见,基于在Page2 上所做的选择。

保持 MRE 的现有结构,这是一种可行的方法。我已将“打开对话框”按钮移至Page1,因为这似乎是最有意义的,但它们也可以在某个单独的页面上,或者如果那里有一些允许的布局,它们也可以合并到 main.qml 中。我还从Page1 建立了一个信号/插槽连接,以触发main.qml 中的Page2 加载(而不是直接尝试访问main.qml 中的对象,这是不好的做法)。我还从Page1 中删除了文本标签以简化代码。 Page2 代码保持不变,所以我不包含它。

ma​​in.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
        }
    }
}

【讨论】:

  • 感谢您抽出宝贵时间阅读该问题。您的解决方案有效并运行,但不幸的是,在我单击Page2 上的选项A 后,我仍然无法在Page1 上看到Button Open Dialog A。我不明白是不是因为StackView
  • @Emanuele 我添加了我看到的屏幕截图(在 qmlscene 应用程序中运行)。如果您没有得到相同的结果,那么您要么没有运行相同的代码,要么存在我不知道的其他差异,抱歉。
  • 对不起,这是一个复制/粘贴问题!。它完全按照您的描述工作。我看到你是如何组织和纠正这个例子的。最重要的是,我看到了应该如何调用对话框。额外的signal selectDialog() 是个好主意。非常感谢您的帮助! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
  • 2017-08-27
  • 1970-01-01
相关资源
最近更新 更多