【问题标题】:Closing qml dialog properly正确关闭 qml 对话框
【发布时间】:2016-11-16 22:04:53
【问题描述】:

我一直在玩对话框,有些事情让我很困扰。

我有以下代码:

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Button {
        id: click
        x: 285
        y: 189
        text: qsTr("Click")
        onClicked: dlgTest.open()
    }

    Dialog{
        id:dlgTest
        visible:false
        contentItem: Rectangle{
            width: 300
            height: 300
            TextField{
                id: tfText
                anchors.top: parent.top
            }
            Button{
                anchors.top: tfText.bottom
                onClicked: dlgTest.close()
                text: "Close"
            }


        }
    }
}

当我第一次打开它时,我会在 TextField 中添加一些文本,然后关闭它。但是,如果我再次打开它,文本仍然存在。我想要的是在我第一次打开它时将对话框“重置”到它的原始状态(使用一个空的 TextField)。看来调用方法“close”和把 visible 改成 false 是一模一样的。

有没有办法“重置”?

我还有一个包含很多控件的对话框,手动恢复所有内容很烦人。

【问题讨论】:

    标签: qt qml qtquick2 qtquickcontrols


    【解决方案1】:

    在您的代码中,您创建一次对话框,作为ApplicationWindow 的子项。 要“重置”它,您有两种选择:

    • 有一个重置功能,您可以调用它并恢复所有内容。您也可以首先使用它进行设置
    • 创建一个新对象,所有内容都已设置到位。

    对于后者,您可以使用 JavaScript 动态对象创建或 Loader

    JavaScript 动态对象创建:

    Button {
        id: click
        x: 285
        y: 189
        text: qsTr("Click")
        onClicked: {
            var d = diaComp.createObject(null)
            d.open()
        }
    }
    
    
    Component {
        id: diaComp
        Dialog{
            id:dlgTest
            visible:false
            contentItem: Rectangle{
                width: 300
                height: 300
                TextField{
                    id: tfText
                    anchors.top: parent.top
                }
                Button{
                    anchors.top: tfText.bottom
                    onClicked: {
                        dlgTest.close()
                        dlgTest.destroy()
                    }
                    text: "Close"
                }
            }
        }
    }
    

    但是,当您销毁对象时,您的属性内容会丢失,您无法再访问它们。所以你需要确保,首先将它们复制(而不是绑定它们)到一些没有被破坏的属性。

    使用Loader,您可以在再次加载对话框之前将其卸载,这基本上会重置它。但在您卸载它之前,您仍然可以访问它的值,正如您在 Buttons onClicked-handler 中看到的那样。

    Button {
        id: click
        x: 285
        y: 189
        text: qsTr("Click")
        onClicked: {
            console.log((dlgLoad.status === Loader.Ready ? dlgLoad.item.value : 'was not loaded yet'))
            dlgLoad.active = false
            dlgLoad.active = true
            dlgLoad.item.open()
        }
    }
    
    Loader {
        id: dlgLoad
        sourceComponent: diaComp
        active: false
    }
    
    
    Component {
        id: diaComp
        Dialog{
            id:dlgTest
            visible:false
            property alias value: tfText.text
            contentItem: Rectangle{
                width: 300
                height: 300
                TextField{
                    id: tfText
                    anchors.top: parent.top
                }
                Button{
                    anchors.top: tfText.bottom
                    onClicked: {
                        dlgTest.close()
                    }
                    text: "Close"
                }
            }
        }
    }
    

    当然,您也可以复制加载器项中的值,然后提前卸载它,以释放内存。

    但如果Dialog 经常(大部分时间)显示,最明智的做法可能是避免创建和销毁对象,方法是重用它并手动重置它。

    【讨论】:

    • 你可以通过sourceComponent: Dialog { ... }直接在LoadersourceComponent属性中声明Dialog组件。您不必显式创建 Component 对象,您可以像这样内联定义它,委托也是如此。
    • 你是对的。但是,如果我使用 Component 来设置更复杂的结构,并设置多个属性,甚至可能是信号处理程序,我认为代码更具可读性。通常,我也会先在单独的文件中声明Dialog。但即便如此,如果需要的绑定太多,我还是先将其放在Component 中。但这可能只是个人口味。我不喜欢使用装载机的source,并在装载机准备就绪时设置所有内容。并使用ConnectionsBindings 等等...
    • 这正是我所需要的!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多