在qml中,如何在filedialog中接受对话框时显示busyIndi​​cator?

时间:2015-04-16 09:34:53

标签: qml

我希望在FileDialog中用户接受文件名后应用程序处理任务时显示busyindicator,但看起来主要线程被filedialog阻止。因此无法显示busyindicator。我该如何解决?感谢

代码如下:

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

ApplicationWindow {
    title: qsTr("Hello World")
    id: root
    width: 640
    height: 480

    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            MenuItem {
                text: qsTr("E&xit")
                onTriggered: Qt.quit();
            }
        }
    }

    MainForm {
        anchors.fill: parent
        button1.onClicked: {
            exportXlsxDialog.open()
        }
        FileDialog {
            id: exportXlsxDialog
            title: qsTr("Please choose a xslx file")
            nameFilters: [ "Excel 2007-2013 (*.xlsx)" ]
            selectExisting: false
            onAccepted: {
                busyIndicator.running = true
                sleep(10000)
                console.log(fileUrl)
                busyIndicator.running = false
            }
            function sleep(milliseconds) {
                var start = new Date().getTime();
                for (var i = 0; i < 1e7; i++) {
                    if ((new Date().getTime() - start) > milliseconds){
                        break;
                    }
                }
            }
        }
        BusyIndicator {
            id: busyIndicator
            z: 99
            anchors.centerIn: parent
            running: false
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我认为问题在于你的sleep()函数没有给BusyIndicator一个机会显示,可能是因为它不会让Qt的事件循环旋转。

最好的解决方案可能是使用WorkerScript,但如果你很懒,你可以使用它:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2

ApplicationWindow {
    title: qsTr("Hello World")
    id: root
    width: 640
    height: 480

    Timer {
        id: expensiveOperationDelay
        interval: 1
        onTriggered: sleep(2000)
    }

    function sleep(milliseconds) {
        var start = new Date().getTime();
        for (var i = 0; i < 1e7; i++) {
            if ((new Date().getTime() - start) > milliseconds){
                break;
            }
        }
        busyIndicator.running = false
    }

    Button {
        text: "Click"
        onClicked: {
            busyIndicator.running = true
            expensiveOperationDelay.start()
//            sleep(2000)
        }
    }

    BusyIndicator {
        id: busyIndicator
        z: 99
        anchors.centerIn: parent
        running: false
    }
}

我简化了你的例子,因为没有必要用对话来证明这个问题。

这将启动昂贵操作的责任推到Timer。我给它一个最小的间隔,导致事件被处理(我认为0的间隔会导致,但显然不会),以便显示指标。我还必须将指示器的隐藏移动到sleep()函数的末尾,因为如果我将它保留在原来的位置,它将在它被渲染之前再次被隐藏。