BusyIndicator does not show up

qml, qt, qtquick2, qtquickcontrols

Solution

There is a way to do this using `QQuickWindow`'s `afterSynchronizing` signal:

import QtQuick 2.4
import QtQuick.Controls 1.3

ApplicationWindow {
    width: 400
    height: 400
    visible: true

    Component.onCompleted: print(Qt.formatDateTime(new Date(), "mm:ss:zzz"), "QML loaded")

    onAfterSynchronizing: {
        print(Qt.formatDateTime(new Date(), "mm:ss:zzz"), "Window content rendered")
        if (!loader.item) {
            loader.active = true
        }
    }

    Item {
        anchors.fill: parent

        BusyIndicator {
            running: !loader.item
            anchors.centerIn: parent
        }

        Loader {
            id: loader
            active: false
            anchors.fill: parent
            sourceComponent: Text {
                wrapMode: Text.Wrap

                Component.onCompleted: {
                    for (var i = 0; i < 500; ++i) {
                        text += "Hello, ";
                    }
                }
            }
        }
    }
}

The idea is to use a `Loader` to have control over when the expensive operation happens. You could also use a dynamically loaded component via `Qt.createQmlObject()`, or `Qt.createComponent()` to dynamically load a component in a separate file.

If you run the example, you'll see that you get the following output:

qml: 58:12:356 QML loaded qml: 58:12:608 Window content rendered

We use `QQuickWindow`'s `afterSynchronizing` signal to know when the content of the window has been displayed, and only act on it the first time (via `if (!loader.item)`).

When the signal is initially emitted, we can be sure that the `BusyIndicator` has started its animation, so the user will actually see a spinning icon.

Once the `Loader` has finished loading the text, its `item` property will become non-null and the `BusyIndicator` will disappear.

Problem

I want to show a `BusyIndicator` while a long process is going on. The problem is it does not show up when I make it run and shows afterwards when the process is completed. According to the docs The busy indicator should be used to indicate activity while content is being loaded or the UI is blocked waiting for a resource to become available. I have created a minimal code that based upon the original code ``` Window { id: win width: 300 height: 300 property bool run : false Rectangle { anchors.fill: parent BusyIndicator { anchors.centerIn: parent running: run } MouseArea { anchors.fill: parent onClicked: { run = true for(var a=0;a<1000000;a++) { console.log(a) } run = false } } } } ``` So when the `Rectangle` is clicked I want to display the `BusyIndicator` for the time till the calculations gets completed. For example purpose I have used the for loop here. In actual scenario I call a function (which inserts some 1000 rows into the Database) through the `ContextProperty`. But in that case too the `BusyIndicator` is not displayed. Am I doing it the right way? Or what would be the best way to do it?

Original source