Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QML: running functions in parallel threads

In my code I'm creating 16x16 buttons in cycle and this take few seconds.

onCreateField:
{
    for(var i=0;i<fieldWidth;i++)
    {
        for(var j=0;j<fieldHeight;j++)
        {
            createButton(i, j);
        }
    }
}

function createButton(x, y)
{
    __buttonX = x;
    __buttonY = y;

    __component = Qt.createComponent("GameButton.qml");

    if(__component != null)
        continueButtonCreation();
    else
        __component.ready.connect(continueButtonCreation);
}

function continueButtonCreation()
{
    var button = __component.createObject(field, {"row": __buttonY, "column": __buttonX});

     if (button == null) {
         // Error Handling
         console.log("Error creating object");

         return;
     }

     updateValveState.connect(button.stateUpdated);
     button.buttonClicked.connect(buttonClicked);

     field.clearField.connect(button.release);
}

While function that creating buttons runs, app freezes. I want to show loading animation while this function runs. So, how to run this function in parallel thread to avoid freezing?

like image 550
Robotex Avatar asked Apr 15 '13 22:04

Robotex


3 Answers

To do work in threads you have two possible approaches :

  1. Read about the WorkerScript element. It allows you to perform certain operation by running the javascript functions as threads.

Note: As given in the documentation, there is a restriction though :

Since the WorkerScript.onMessage() function is run in a separate thread, the JavaScript file is evaluated in a context separate from the main QML engine. This means that unlike an ordinary JavaScript file that is imported into QML, the script.js in the above example cannot access the properties, methods or other attributes of the QML item, nor can it access any context properties set on the QML object through QDeclarativeContext. Additionally, there are restrictions on the types of values that can be passed to and from the worker script. See the sendMessage() documentation for details.

Just see, if for your particular use case it suits the requirement.

2 . Implement the functionality which are heavy as C++ threads. Whenever required, generate a signal to start this thread on the C++ side. When done, pass back the data from C++ to Qml , if required.

like image 79
Amit Tomar Avatar answered Sep 30 '22 14:09

Amit Tomar


As you may or may not have determined in other posts you cannot load QML objects in javascript in parallel. Depending on your circumstances you should probably be using a GridView with a Delegate that renders a button. This allows the underlying code to efficently render the buttons instead of sequentially creating them in javascript.

like image 42
Deadron Avatar answered Sep 30 '22 14:09

Deadron


Other options to not block the UI might be

  • use incubateObject instead of createObject
  • don't create all Buttons within a single (16ms) frame: use a Timer to spread the creation of the Buttons over multiple frames
like image 29
Marc Van Daele Avatar answered Sep 30 '22 16:09

Marc Van Daele