同步窗口.显示()

Synchronous Window.show()

本文关键字:显示 窗口 同步      更新时间:2023-09-26

在我的项目中,我使用从Window派生的自定义组件来显示消息。目前我使用此代码:

function showMessage(title, text) {
    var component = Qt.createComponent("MessageBox.qml");
    if (component.status === Component.Ready) {
        var dialog = component.createObject(parent);
        dialog.caption = title;
        dialog.message = text;
        dialog.show();
        return dialog;
    }
}

但是现在我想在 JS 中将其用作一种confirm(),即现在它应该等到用户单击对话框中的相应按钮,因此在此之后返回值(真/假)。

期望的用法之一是验证用户表单,例如:

function checkAForm() {
    if(!showMessage("Warning","The field f1 is empty. Do you want to continue?"))
        return false;
    if(!showMessage("Warning","Some warning"))
        return false;
    if(!showMessage("Warning","Some another warning"))
        return false;
    return true;
}

现在此函数总是同时打开 3 个窗口并返回 false .

第一个想法是通过信号连接来实现这一点:

function checkAForm() {
    var dialog1 = showMessage("...","...");
    dialog1.accepted.connect(function(){
        var dialog2 = showMessage("...","...");
        dialog2.accepted.connect(function(){
            var dialog3 = showMessage("...","...");
            dialog3.accepted.connect(function(){
                return true;
            });
        });
    });
}

其中accepted是用户单击按钮时发出的MessageBox.qml信号Ok

但是这个结构太复杂了,不是那么清楚。我也不知道如果使用点击Cancel该怎么办.

所以现在我正在寻找如何实现 Window.show() 的同步调用的好主意,或者可能是一些其他的想法,也许是一些信号量或类似的东西。

据我从评论中了解到,似乎同步性/异步性(阻塞或不阻塞 GUI 线程)可能不是这里的问题,但您希望在一个序列中有多个对话框窗口,在我看来这有点像向导。

为此,使用您当前的方法,为什么不做这样的事情:

首先,您将像这样设置自定义 MessageBox.qml:

Item {
...
    property var acceptedFunction
    property var canceledFunction
...
    Button {
        id: acceptedButton
        onClicked: { acceptedFunction() }
    }
    Button {
        id: canceledButton
        onClicked: { canceledFunction() }
    }
...
}

然后,在利用 qml 中:

    function startTheShow() {
        showFirstWindow()
    }
    function showFirstWindow() {
        var title = "First Window's Title"
        var text = "First Window's Text"
        var component = Qt.createComponent("MessageBox.qml");
        if (component.status === Component.Ready) {
            var dialog = component.createObject(parent);
            dialog.caption = title;
            dialog.message = text;
            dialog.acceptedFunction = showSecondWindow
            dialog.canceledFunction = function() { ...do something here... } //This is just for an example how you can have it also -- as an anonymous function.
            dialog.show();
        }
    }
    function showSecondWindow() {
        var title = "Second Window's Title"
        var text = "Second Window's Text"
        var component = Qt.createComponent("MessageBox.qml");
        if (component.status === Component.Ready) {
            var dialog = component.createObject(parent);
            dialog.caption = title;
            dialog.message = text;
            dialog.acceptedFunction = showThirdWindow
            dialog.canceledFunction = function() { ...do something here... } //This is just for an example how you can have it also -- as an anonymous function.
            dialog.show();
        }
    function showThirdWindow() ...and so on

如果你摆弄上面的内容,你也可以用一个通用函数和一个对象数组作为窗口流的配置来做到这一点。也许像这样:

MessageBox.qml:

Item {
...
    property int myIndex
    property var showNextWindowFunc
    Button {
        id: acceptedButton
        onClicked: { showNextWindowFunc(myIndex+1) }
    }
    Button {
        id: canceledButton
        onClicked: { ...do some standard thing perhaps?... }
    }
...
}

利用Qml.qml:

property var myWindowSequenceConfiguration: [
    { "title" : "Title 1", "text" : "Text 1" },
    { "title" : "Title 2", "text" : "Text 2" },
    ...
]
function showWindow(index) {
    var component = Qt.createComponent("MessageBox.qml");
    if (component.status === Component.Ready) {
        var dialog = component.createObject(parent);
        dialog.myIndex = index
        dialog.caption = myWindowSequenceConfiguration[index]["title"];
        dialog.message = myWindowSequenceConfiguration[index]["text"];
        dialog.showNextWindowFunc = showWindow
        dialog.show();
    }
}
function startTheShow() {
    showWindow(0)
}

好的,我想出了主题的另一个变体:

MessageBox.qml:

Item {
...
    property var acceptedFuncParams
    property var canceledFuncParams
    property var acceptedFunc
    property var canceledFunc
    Button {
        id: acceptedButton
        onClicked: { acceptedFunc(acceptedFuncParams) }
    }
    Button {
        id: canceledButton
        onClicked: { canceledFunc(canceledFuncParams) }
    }
...
}

利用Qml.qml:

property var myWindowSequenceConfiguration: [
    { "title" : "Title 1", "text" : "Text 1" },
    { "title" : "Title 2", "text" : "Text 2" },
    ...
]
function showWindow(index) {
    var component = Qt.createComponent("MessageBox.qml");
    if (component.status === Component.Ready) {
        var dialog = component.createObject(parent);
        dialog.caption = myWindowSequenceConfiguration[index]["title"];
        dialog.message = myWindowSequenceConfiguration[index]["text"];
        dialog.acceptedFuncParams = index+1
        dialog.acceptedFunc = showWindow
        dialog.canceledFunc = function() { ...do something here... }
        dialog.show();
    }
}
function startTheShow() {
    showWindow(0)
}