当用户按下按钮时,我需要一个确认或警告对话框。根据他们是选择“是”还是“否”,会触发不同的操作。挑战在于我有两个按钮弹出这样的对话框,在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()
}
}
}
}
在传统编程中,弹出一个单独的对话框,该对话框完全响应该问题,而不是响应其cancelled()
或accepted()
信号。在QML中我们不能真的这样做,对吗?知道按下哪个按钮的最佳方法是什么?具有讽刺意味的是,即使发出正确的信号,我们也似乎无法对它们采取行动。
答案 0 :(得分:2)
嗯,首先,您应该真正了解Dialogs
模块,因为它为您提供了现成的解决方案,即MessageDialog
。
也就是说,您可以通过不同方式实现自定义,包括重新定义处理程序或传递id
。如果要执行的操作很简单(例如函数调用),您甚至可以动态创建对话框并使用所需的行为绑定信号。自定义显然可以更进一步,更改title
和text
。
这是一个简单的示例,它遵循最后一种方法,并根据按下的按钮打印不同的文本。一旦对话框设置为不可见,它将通过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
}
}
}
如果您想使用Rectangle
或被迫使用它,那么您仍然可以使用此方法。动态创建对象与MessageDialog
的使用无关,可以使用(并且应该使用)来减少在整个应用程序生命周期中保持实例化的对象数。有关详细信息,请查看here。
以下示例使用您定义的完全相同的对话框组件(稍作修改。正如您所看到的,代码几乎相同。我刚刚在信号处理程序的末尾移动了对象的破坏。 case我还更改了组件中定义的唯一属性的值,即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()
}
}
}
}
}
如果您的组件没有像Component
那样内联,但它保存在另一个文件中,您可以使用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
。