QMLでもマルチスレッド処理できます。
「WorkerScript」エレメントを使用して実装します。
/// 今回のポイント ///
・スレッド間でやり取りできるデータは以下の3種類。
・boolean, number, string型
・JavaScript objectと配列
・ListModel object (他のQObjectはNG)
3つ目のListModelが渡せるのが最重要。
・WorkerスレッドでListModelにアイテムを更新したときは「sync」メソッドで更新。
/// 手順的な箇条書き ///
・メインスレッドからスレッドの起動は「sendMessage(jsobject)」
・Workerスレッドで受けるメソッドは「WorkerScript.onMessage(jsobject)」
・Workerスレッドからメインスレッドへの通信は「WorkerScript.sendMessage(jsobject)」
・メインスレッドで受けるonMessageシグナルの引数は「messageObject」
どう考えても裏で情報いっぱい取得とかして順次ListViewへ表示するためって感じですね。
なので、わかりやすいサンプルを作って見ました。
「Click」ってところをクリックすると1秒間隔でリストへアイテムを追加する動作をします。
アイテムを追加していく過程でもリストをドラッグしてうにょーんて動かせます。
とまっててわかりにくいスクリーンショット
メインスレッドからもWorkerスレッドからも通信メソッドが「sendMessage」なのがなんとなく不思議な感じがしなくもないです。
<Category : Qt>
「WorkerScript」エレメントを使用して実装します。
/// 今回のポイント ///
・スレッド間でやり取りできるデータは以下の3種類。
・boolean, number, string型
・JavaScript objectと配列
・ListModel object (他のQObjectはNG)
3つ目のListModelが渡せるのが最重要。
・WorkerスレッドでListModelにアイテムを更新したときは「sync」メソッドで更新。
/// 手順的な箇条書き ///
・メインスレッドからスレッドの起動は「sendMessage(jsobject)」
・Workerスレッドで受けるメソッドは「WorkerScript.onMessage(jsobject)」
・Workerスレッドからメインスレッドへの通信は「WorkerScript.sendMessage(jsobject)」
・メインスレッドで受けるonMessageシグナルの引数は「messageObject」
どう考えても裏で情報いっぱい取得とかして順次ListViewへ表示するためって感じですね。
なので、わかりやすいサンプルを作って見ました。
「Click」ってところをクリックすると1秒間隔でリストへアイテムを追加する動作をします。
アイテムを追加していく過程でもリストをドラッグしてうにょーんて動かせます。
とまっててわかりにくいスクリーンショット
メインスレッドからもWorkerスレッドからも通信メソッドが「sendMessage」なのがなんとなく不思議な感じがしなくもないです。
import QtQuick 1.0
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);
}
}
// リストの初期アイテム
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
}
}
}
// リスト
ListView{
anchors.top: _btn.bottom
anchors.left: _root.left
anchors.right: _root.right
anchors.bottom: _root.bottom
clip: true
model: _model
delegate: _delegate
}
}
// 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);
}

