2016-06-23 21 views
0

私のUIプロジェクトで信号を使って実験しています。私はボタンをいくつかのプロセスを開始したい。私がこれをやっている間、私は何が起こっているのか分からなかったことに気がついたので、私は起こっていたことをピンポイントで調べるために以下のコードを書きました。qmlプロパティの更新はどのように整理されていますか?

実行すると、main.qmlはいくつかの色付きボックスをコントロールとして作成し、出力用に白いボックス(SubOne.qmlから作成)を作成します。

緑色のボックスをクリックすると、信号「ブロードキャスト」が放射され、各白いボックスがその信号に接続されます。

「ブロードキャスト」では、各白いボックスがその機能バーを呼び出します。

バーがループを開始します。ループの終わりには反復回数が出力され、テキストプロパティは同じ数に変更されます。

第1と第3の白いボックスは1ループですが、第2のボックスは目立つ遅延を引き起こすのに十分なループを行います。

すべては問題ありません。予想どおり、3つのファンクションバーは順次呼び出され、順番に出力されます。しかし、私は、テキストプロパティが順番に更新されないことに驚いていました。すべてのバーが終了し、3つのテキストプロパティがすべて一緒に更新されます。

つまり、SubOne.qmlでは、17行目はALLループが完了するまで有効になりませんが、18行目はEACHループが完了すると有効になります。

何が起こっているのか教えていただけますか? qmlはディスプレイへの書き込みを最適化するために何かしていますか?そうであれば、それを制御することができます。

主に、各ループが終了した後、印刷とテキストの更新を一緒に行うことができます。

ありがとうございました。ここで

//qml.main

import QtQuick 2.4 
import QtQuick.Controls 1.3 

ApplicationWindow { 
    visible: true 

    Rectangle { 
     Rectangle { 
      x: 50 
      y: 50 
      width: 50 
      height: 50 
      color: "green" 
      Text { 
       text: "Start" 
       anchors.horizontalCenter: parent.horizontalCenter 
       anchors.verticalCenter: parent.verticalCenter 
      } 
      MouseArea { 
       id: start 
       signal broadcast() 
       anchors.fill: parent 
       onClicked: broadcast(); 
      } 

     } 
     Rectangle { 
      function set() { 
       first.thisText = "---"; 
       second.thisText = "---"; 
       third.thisText = "---"; 
      } 
      id: reset 
      x: 110 
      y: 50 
      width: 50 
      height: 50 
      color: "yellow" 
      Text { 
       text: "Reset" 
       anchors.horizontalCenter: parent.horizontalCenter 
       anchors.verticalCenter: parent.verticalCenter 
      } 
      MouseArea { 
       anchors.fill: parent 
       onClicked: reset.set(); 
      } 
     } 
     Rectangle { 
      id: exit 
      x: 170 
      y: 50 
      width: 50 
      height: 50 
      color: "red" 
      Text { 
       text: "Exit" 
       anchors.horizontalCenter: parent.horizontalCenter 
       anchors.verticalCenter: parent.verticalCenter 
      } 
      MouseArea { 
       anchors.fill: parent 
       onClicked: Qt.quit(); 
      } 
     } 
    } 


    SubOne { 
     id: third 
     thisName: "third" 
     x: 50 
     y: 110 
     loop: 1 
    } 
    SubOne { 
     id: second 
     thisName: "second" 
     x: 50 
     y: 170 
     loop: 100000000 
    } 
    SubOne { 
     id: first 
     thisName: "first" 
     x: 50 
     y: 230 
     loop: 1 
    } 

} 

//SubOne.qml

import QtQuick 2.0 

Rectangle { 
    id: rectangle1 
    property string thisName: "" 
    property string thisText: "nothing yet" 
    property int loop: 1 
    height:50 
    width:170 

    function bar() { 
     print("looping " + thisName + " with: " + loop); 
     for (var counter=0; counter<loop; counter+=1){ 
      //do nothing much 
     } 
     thisText = counter; 
     print("looped " + thisName + " to: " + counter); 
    } 

    Text { 
     text: thisText 
     anchors.horizontalCenter: parent.horizontalCenter 
     anchors.verticalCenter: parent.verticalCenter 
    } 

    Connections { 
     target: start 
     onBroadcast: bar() 
    } 
} 

示唆したように、WorkerScriptを使用して、新しいコードです。

//SubOne.qml

import QtQuick 2.0 

Rectangle { 
    id: rectangle1 
    property string thisName: "" 
    property string thisText: "nothing yet" 
    property int loop: 1 
    height:50 
    width:170 

    WorkerScript { 
     id: myWorker 
     source: "script.js" 
     onMessage: thisText = messageObject.reply 
    } 

    Text { 
     text: thisText 
     anchors.horizontalCenter: parent.horizontalCenter 
     anchors.verticalCenter: parent.verticalCenter 
    } 

    Connections { 
     target: start 
     onBroadcast: { 
      myWorker.sendMessage({'loopVal':loop, 'nameVal':thisName}); 
     } 
    } 
} 

//script.js

WorkerScript.onMessage = function(obj) { 
    print("looping " + obj.nameVal + " to: " + obj.loopVal); 
    for (var counter=0; counter<obj.loopVal; counter+=1){ 
     //do nothing much 
    } 
    print("finished " + obj.nameVal + " at: " + counter); 
    WorkerScript.sendMessage({ 'reply': counter}) 
} 

SubOne.qmlのライン26上のsendMessageがでのonMessageによって処理されないことは注目に値しますSubOneの14行目はscript.jsの1行目のWorkerScript.onMessageによって処理され、同様にscript.jsの7行目のWorkerScript.sendMessageは14行目のSubOne.qmlファイルで処理されます。また、新しいスレッドに送られたメッセージは1つのパラメータだけを取得するので、nameValとloopValを送信するにはオブジェクトには、ラインにインラインを作成SubOne.qml

の26

たぶんそれは明白ですが、それはしばらくの間、私を混同し、

その興味深いあなたがループ中に「赤」を押した場合には、メイン)スレッドはすぐに終了しますが、2番目のスレッドは最初に何を行ったのかを完了します。

これは誰かを助けることを望みます。

そして、BaCaRoZzoとKuba Oberのおかげです。

+0

Kuba Oberが指摘するように、あなたはメインスレッドをブロックしています。 GUIは、まったく同じスレッドで更新されます。問題のコードを作業スレッドにオフロードする必要があります。可能なアプローチについては、['WorkerScript'](http://doc.qt.io/qt-5/qml-workerscript.html#details)を見てみてください。 – BaCaRoZzo

+1

ああ、もちろん。私はそれを考えていたはずです。私はそれをWorkerScriptを使用するよう書き直し、できるだけ早く他の人のために投稿します。あなたのおかげで両方。 –

答えて

3

QMLはここではあまり何もしていません。イベントループをブロックしているからです。あなたのコードが実行されているとき、イベントループはありません。QMLが表示更新を行う方法はありません。ディスプレイを更新するには、制御をイベントループに戻す必要があります。これは、ウィジェットベースのUIと変わりはありません。そこにも同じ行動があります。

関連する問題