Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

QML WorkerScript Threading Example Analysis

Tech May 14 1

Key Class Overview

The QML framework provides a WorkerScript component that has a source property to load JavaScript files. It includes a message signal, which implies a default onMessage handler. Additionally, it offers a method to send messages to a function named WorkerScript.onMessage (executed in the background thread). The message handling function can use WorkerScript.sendMessage to send data back to the main thread. A detailed description of the WorkerScript class is shown in Figure 1.

Figure 1: WorkerScript Description

Example Analysis

This example demonstrates two simple uses of WorkerScript, applied in the timedisplay.qml and workerscript.qml components.

Updating View Data

As shown in Figure 2, this is a basic use of WorkerScript. The QML file sends a message to the JavaScript function, which updates the view content. The message flow is: UI thread -> background thread processing (calls interface to update UI).

Figure 2: Updating View Data

The UI file content is as follows. Every 2 seconds, the timer triggers, sending a message to the JavaScript function via worker.sendMessage. The JavaScript file is specified by the source property of the WorkerScript object, as seen in line 17 of the code below:

1 Rectangle {
2     color: "white"
3     width: 200
4     height: 300
5 
6     ListView {
7         anchors.fill: parent
8         model: listModel
9         delegate: Component {
10             Text { text: time }
11         }
12 
13         ListModel { id: listModel }
14 
15         WorkerScript {
16             id: worker
17             source: "dataloader.js"
18         }
19 
20 // ![0]
21         Timer {
22             id: timer
23             interval: 2000; 
24             repeat: true
25             running: true
26             triggeredOnStart: true
27 
28             onTriggered: {
29                 var msg = {'action': 'appendCurrentTime', 'model': listModel};
30                 worker.sendMessage(msg);
31             }
32         }
33 // ![0]
34     }
35 }

The corresponding JavaScript file dataloader.js is simple, containing just one function. The code is as follows:

1 WorkerScript.onMessage = function(msg) {
2     if (msg.action == 'appendCurrentTime') {
3         var data = {'time': new Date().toTimeString()};
4         msg.model.append(data);
5         msg.model.sync();
6     }
7 }

Wheel Game

Figure 3 shows a more complex usage of WorkerScript, where the message flow is: UI thread -> background thread -> UI thread.

Figure 3: Wheel Game

The wheel game code is relatively simple, so I will only present the key parts:

1 WorkerScript {
2         id: myWorker
3         source: "workerscript.js"
4 
5         onMessage: {
6             if (messageObject.row == rowSpinner.value && messageObject.column == columnSpinner.value){
7                 if (messageObject.result == -1)
8                     resultText.text = "Column must be <= Row";
9                 else
10                     resultText.text = messageObject.result;
11             }
12         }
13     }
14 //! [1]
15     Row {
16         y: 24
17         spacing: 24
18         anchors.horizontalCenter: parent.horizontalCenter
19 //! [0]
20         Spinner {
21             id: rowSpinner
22             label: "Row"
23             onValueChanged: {
24                 resultText.text = "Loading...";
25                 myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
26             }
27         }
28 //! [0]
29 
30         Spinner {
31             id: columnSpinner
32             label: "Column"
33             onValueChanged: {
34                 resultText.text = "Loading...";
35                 myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
36             }
37         }
38     }

The Spinner is a custom component that exports the current text and index properties. The corresponding JavaScript file is as follows:

1 var cache = new Array(64);
2 for (var i = 0; i < 64; i++)
3     cache[i] = new Array(64);
4 
5 function triangle(row, column) {
6     if (cache[row][column])
7         return cache[row][column]
8     if (column < 0 || column > row)
9         return -1;
10     if (column == 0 || column == row)
11         return 1;
12     return triangle(row-1, column-1) + triangle(row-1, column);
13 }
14 //! [0]  
15 WorkerScript.onMessage = function(message) {
16     var calculatedResult = triangle(message.row, message.column);
17     WorkerScript.sendMessage( { row: message.row,
18                                 column: message.column,
19                                 result: calculatedResult} );
20 }
21 //! [0]

The JavaScript file is not discussed further. This example primarily aims to analyze the use of WorkerScript. With the two methods above, it should be possible to understand its functionality.

Tags: QML

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.