I have a qml application which performs a rather long action upon a users request. During the time, I want to display an overlay over the whole screen, so the user is aware that the application is working, basically a busy indicator.
My Problem is, that the application starts with the task, before updating the UI component. Here's a minimal example to demonstrate the problem:
import QtQuick 2.9
import QtQuick.Window 2.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Ui Demo")
Rectangle {
id: rectangle
anchors.fill: parent
color: "green"
}
MouseArea {
id: action
anchors.fill: parent
onClicked: {
rectangle.color = "red"
for(var i = 0; i < 10000; i++)
console.log(i)
}
}
}
What I want is, that the Rectangle
s color turns red while the for
loop is running, but the behavior I see is that the color changes only after the loop has finished.
I also tried the following with no difference:
Rectangle {
id: rectangle
anchors.fill: parent
color: "green"
onColorChanged: {
for(var i = 0; i < 10000; i++)
console.log(i)
}
}
I know, that the cleanest solution would be to perform the heavy work on a different thread to not block the UI thread. But I do not wish to do this, because in my actual application the blocking work is updating a ListModel, which (as noted here for example)
Qt views unfortunately don't know how to deal with [when they are] in foreign threads.
So I would need to implement a new, asynchronous Model class, which is effort and time my customer is currently not willing to pay for.
Therefor my question is: How can I make sure, that the UI is redrawn/updated as soon as I set the property?