QML中可重用的确认提示

QML中可重用的确认提示,qml,qt5,qtquick2,Qml,Qt5,Qtquick2,当用户按下按钮时,我需要一个确认或警报对话框。根据他们选择“是”或“否”,会触发不同的操作。挑战在于我有两个弹出这样一个对话框的按钮,如何在QML中实现这一点并不简单。以下是代码(我的演示应用程序): main.qml import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Controls 1.4 Window { visible: true function areYouSure() {

当用户按下按钮时,我需要一个确认或警报对话框。根据他们选择“是”或“否”,会触发不同的操作。挑战在于我有两个弹出这样一个对话框的按钮,如何在QML中实现这一点并不简单。以下是代码(我的演示应用程序):

main.qml

import QtQuick 2.5
import QtQuick.Window 2.2

import QtQuick.Controls 1.4

Window {
    visible: true

    function areYouSure()
    {
        prompt.visible = true
    }

    MainForm {
        anchors.fill: parent

        Button {
            id: buttonA
            anchors.left: parent.left
            anchors.top: parent.top
            text: "Button A"

            onClicked: areYouSure() // based on yes or no, different actions but how to tell what was pressed?
        }

        Button {
            id: buttonB
            anchors.right: parent.right
            anchors.top: parent.top
            text: "Button B"

            onClicked: areYouSure() // based on yes or no, different actions but how to tell what was pressed?
        }
    }

    Prompt {
        anchors.fill: parent
        id: prompt
        visible: false

        onCancelled: {
            console.log("Cancel was pressed")
            // but how can I tell which button's cancel as pressed?
        }

        onAccepted: {
            console.log("Accept was pressed")
            // same for which button's Ok?
        }
    }
}
Prompt.qml

import QtQuick 2.5
import QtQuick.Window 2.2

import QtQuick.Controls 1.4

Rectangle
{
    id: root
    width: parent.width

    property string message: "Are you Sure?"

    signal cancelled;
    signal accepted;


    Text{
        id: messagetxt
        text:root.message
        horizontalAlignment: Text.AlignHCenter
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter

    }

    Rectangle {
        id: cancelButton
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        width: 50
        height: 40

        Text {
            anchors.centerIn: parent
            text: "Cancel"
        }
        color: "red"

        MouseArea {
            anchors.fill: parent

            onClicked: {
                root.visible = false
                cancelled()
            }
        }
    }

    Rectangle {
        id: okButton
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        width: 50
        height: 40

        Text {
            anchors.centerIn: parent
            text: "Ok"
        }
        color: "blue"

        MouseArea {
            anchors.fill: parent

            onClicked: {
                root.visible = false
                accepted()

            }
        }
    }
}

在传统编程中,会弹出一个单独的对话框,该对话框准确地响应该问题,然后我们响应其
取消()
接受()
信号。在QML中,我们不能真正做到这一点,对吗?知道按下哪个按钮的最佳方法是什么?具有讽刺意味的是,即使发出了正确的信号,我们似乎也无法对其采取行动。

首先,您应该真正了解一下模块,因为它为您提供了现成的解决方案,即
MessageDialog

也就是说,您可以通过不同的方式实现定制,包括重新定义处理程序或传递
id
s。如果要执行的操作很简单(例如函数调用),您甚至可以动态创建对话框,并将信号与所需行为绑定。显然,定制可以更进一步,更改
标题
文本

下面是一个简单的例子,它遵循上一种方法,根据按下的按钮打印不同的文本。对话框设置为不可见后,将通过
destroy
功能将其销毁

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0

ApplicationWindow {
    id: win
    title: qsTr("MultiDialog")
    visible: true

    RowLayout {
        anchors.fill: parent

        Button {
            text: "Button 1"
            onClicked: {
                var d1 = compDialog.createObject(win)
                // change "title" & "text"?
                d1.accepted.connect(function(){
                    console.info("accepted: " + text)
                })
                d1.rejected.connect(function(){
                    console.info("rejected: " + text)
                })
                d1.visible = true
            }
        }

        Button {
            text: "Button 2"
            onClicked: {
                var d2 = compDialog.createObject(win)
                // change "title" & "text"?
                d2.accepted.connect(function(){
                    console.info("accepted: " + text)
                })
                d2.rejected.connect(function(){
                    console.info("rejected: " + text)
                })
                d2.visible = true
            }
        }
    }

    Component {
        id: compDialog

        MessageDialog {
            title: "May I have your attention please"
            text: "It's so cool that you are using Qt Quick."
            onVisibleChanged: if(!visible) destroy(1)
            standardButtons: StandardButton.Cancel | StandardButton.Ok
        }
    }
}
如果您想使用
矩形
或被迫使用它,那么您仍然可以使用这种方法。对象的动态创建与
MessageDialog
的使用无关,可以使用(并且应该使用)来减少在整个应用程序生命周期中保持实例化的对象数量。请看一看有关这方面的更多细节

下面的示例使用与您定义的对话框组件完全相同的组件(进行了一些小的修改。正如您所看到的,代码几乎完全相同。我刚刚将对象的销毁移到了信号处理程序的末尾。在本例中,我还更改了组件中定义的唯一属性的值,即
message
,以显示完整的自定义

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4

Window {
    id: win
    visible: true

    RowLayout {
        anchors.fill: parent

        Button {
            text: "Button 1"
            Layout.alignment: Qt.AlignCenter
            onClicked: {
                var d1 = prompt.createObject(win)
                d1.message = text + " - Are you Sure?"
                d1.accepted.connect(function(){
                    console.info("accepted: " + text)
                    d1.destroy()
                })
                d1.rejected.connect(function(){
                    console.info("rejected: " + text)
                    d1.destroy()
                })
            }
        }

        Button {
            text: "Button 2"
            Layout.alignment: Qt.AlignCenter
            onClicked: {
                var d2 = prompt.createObject(win)
                d2.message = text + " - Are you Sure?"
                d2.accepted.connect(function(){
                    console.info("accepted: " + text)
                    d2.destroy()
                })
                d2.rejected.connect(function(){
                    console.info("rejected: " + text)
                    d2.destroy()
                })
            }
        }
    }

    Component {
        id: prompt

        Rectangle {
            id: root
            anchors.fill: parent

            property string message: "Are you Sure?"

            signal rejected()
            signal accepted()

            Text{
                id: messagetxt
                text:root.message
                horizontalAlignment: Text.AlignHCenter
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
            }

            Rectangle {
                id: cancelButton
                anchors.bottom: parent.bottom
                anchors.left: parent.left
                width: 50
                height: 40

                Text {
                    anchors.centerIn: parent
                    text: "Cancel"
                }
                color: "red"

                MouseArea {
                    anchors.fill: parent
                    onClicked: rejected()
                }
            }

            Rectangle {
                id: okButton
                anchors.bottom: parent.bottom
                anchors.right: parent.right
                width: 50
                height: 40

                Text {
                    anchors.centerIn: parent
                    text: "Ok"
                }
                color: "blue"

                MouseArea {
                    anchors.fill: parent
                    onClicked: accepted()
                }
            }
        }
    }
}
如果您的组件没有像我在
组件
中所做的那样内联,而是保存在另一个文件中,您可以使用上面提供的链接中描述的
createComponent
。主窗口的代码如下所示:

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4

Window {
    id: win
    visible: true
    property var prompt

    RowLayout {
        anchors.fill: parent

        Button {
            text: "Button 1"
            Layout.alignment: Qt.AlignCenter
            onClicked: {
                var d1 = prompt.createObject(win)
                d1.message = text + " - Are you Sure?"
                d1.accepted.connect(function(){
                    console.info("accepted: " + text)
                    d1.destroy()
                })
                d1.rejected.connect(function(){
                    console.info("rejected: " + text)
                    d1.destroy()
                })
            }
        }

        Button {
            text: "Button 2"
            Layout.alignment: Qt.AlignCenter
            onClicked: {
                var d2 = prompt.createObject(win)
                d2.message = text + " - Are you Sure?"
                d2.accepted.connect(function(){
                    console.info("accepted: " + text)
                    d2.destroy()
                })
                d2.rejected.connect(function(){
                    console.info("rejected: " + text)
                    d2.destroy()
                })
            }
        }
    }

    Component.onCompleted: prompt = Qt.createComponent("Prompt.qml");
}
您应该始终检查组件创建是否正确执行(为了简洁起见,我没有这样做)。也就是说,代码与前面的代码相同

最后但并非最不重要的一点是,我注意到您的代码中有一个错误:信号必须总是用括号声明,即使没有发出参数。它应该是
signal accepted()
,而不是
signal accepted
,其他信号和任何其他信号声明也是如此