QMLの基礎 - マルチスレッド
ナビゲーションに移動
検索に移動
概要
QMLとC++を連携させたマルチスレッドの実装手順、および、WorkerScript
を使用したマルチスレッドの実装手順を記載する。
WokerScriptの使用
WokerScriptでやり取りできるデータ型
bool
型、number
型、string
型- JavaScriptオブジェクトと配列
ListModel
(他のオブジェクトは不可)
また、WorkerScript
でListModel
にアイテムを更新した時は、sync
メソッドで反映できる。
処理の手順
- メインスレッドから
WokerScript
を起動する時は、sendMessage(jsobject)
を使用する。 WokerScript
側のメソッドは、WorkerScript.onMessage(jsobject)
を使用する。WokerScript
からメインスレッドへ通信する時は、WorkerScript.sendMessage(jsobject)
を使用する。- メインスレッド側で受ける
onMessage
シグナルの引数は、messageObject
を使用する。
サンプルコード
以下の例では、[Click]を押下する時、1秒間隔でリストへアイテムを追加している。
アイテムを追加している最中でも、リストをドラッグして動かすこともできる。
// main.qml
import QtQuick 2.15
Rectangle {
id: _root
width: 200
height: 360
// ボタン
Rectangle {
id: _btn
width: _root.width
height: _lavel.paintedHeight * 2
color: "#ddddff"
border.color: "#dddddd"
border.width: 1
Text {
id: _lavel
anchors.centerIn: parent
text: "Click!"
}
// スレッド開始処理
MouseArea {
anchors.fill: parent
onClicked: {
console.debug("click");
// スレッド開始
_thread.sendMessage({"model":_model, "number": 20, "string": "Start!"});
}
}
}
// スレッド用エレメント
WorkerScript {
id: _thread
source: "scripts.js" // スレッド処理をするスクリプトファイルの指定
onMessage: {
// Workerスレッドからの通信イベント
console.debug("finish thread:" + messageObject.result + ", split=" + messageObject.split);
}
}
// リスト
ListView {
anchors.top: _btn.bottom
anchors.left: _root.left
anchors.right: _root.right
anchors.bottom: _root.bottom
clip: true
model: _model
delegate: _delegate
}
// リストの初期アイテム
ListModel {
id: _model
ListElement {
_message: "Item"
}
}
// リスト用レイアウト
Component {
id: _delegate
Rectangle {
width: _root.width
height: _text.paintedHeight * 2
border.color: "#dddddd"
border.width: 1
Text {
id: _text
anchors.centerIn: parent
text: _message
}
}
}
}
// scripts.js
WorkerScript.onMessage = function(message)
{
console.debug("start worker script:" + message.number + "," + message.string);
var now = 0;
var split = new Date();
for(var i = 0; i < message.number; i++)
{
delay(1000);
now = new Date();
message.model.append({"_message": i + " : " + Qt.formatDateTime(now, "yyyy/MM/dd hh:mm:ss")});
message.model.sync();
}
split = (new Date()) - split;
// メインスレッドへの応答
WorkerScript.sendMessage({ "result": "tRue", "split": split })
}
// ウエイトを入れる
function delay(msec)
{
var start = 0;
start = new Date();
do
{
now = new Date();
}while((now - start) < msec);
}