QMLの基礎 - マルチスレッド

提供:MochiuWiki : SUSE, EC, PCB
2021年10月26日 (火) 03:52時点におけるWiki (トーク | 投稿記録)による版 (ページの作成:「== 概要 == QMLとC++を連携させたマルチスレッドの実装手順、および、<code>WorkerScript</code>を使用したマルチスレッドの実装手順を…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

概要

QMLとC++を連携させたマルチスレッドの実装手順、および、WorkerScriptを使用したマルチスレッドの実装手順を記載する。


WokerScriptの使用

WokerScriptでやり取りできるデータ型

  • bool型、number型、string
  • JavaScriptオブジェクトと配列
  • ListModel(他のオブジェクトは不可)


また、WorkerScriptListModelにアイテムを更新した時は、syncメソッドで反映できる。

処理の手順

  1. メインスレッドからWokerScriptを起動する時は、sendMessage(jsobject)を使用する。
  2. WokerScript側のメソッドは、WorkerScript.onMessage(jsobject)を使用する。
  3. WokerScriptからメインスレッドへ通信する時は、WorkerScript.sendMessage(jsobject)を使用する。
  4. メインスレッド側で受けるonMessageシグナルの引数は、messageObjectを使用する。


サンプルコード

以下の例では、[Click]を押下する時、1秒間隔でリストへアイテムを追加している。
アイテムを追加している最中でも、リストをドラッグして動かすこともできる。

QML MultiThread 1.png
 // 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);
 }