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); }