2017-02-08 6 views
3

私は関数を実行するために800msの遅延時間を設定したいので、タイマを使って処理します。コードは次のようなものです。しかし、私は最初に関数が正しく実行されていることを発見しました。のconsole.log(ここではコンソール.....)を表示するだけです。が表示されますが、もう一度クリックすると2台のコンソールが表示され、3台目のコンソールには3台のコンソールが表示されます。私は繰り返し= falseを設定してもタイマーが何度も働くのはなぜですか?

これはなぜ起こるのですか?数回のクリック後

import QtQuick 2.6 
import QtQuick.Window 2.2 

Window { 
    visible: true 
    width: 640 
    height: 480 
    title: qsTr("Hello World") 

    MouseArea { 
     anchors.fill: parent 
     onClicked: { 
      delayTimer(800,function(){ 
       console.log("here is console....."); 
       var t= Math.random(); 
       console.log(t); 
      }) 

     } 
    } 



    Timer{ 
     id:dtimer 
    } 

    function delayTimer(delayTime, cb) { 
     console.log("delayTimer is starting"); 
     dtimer.interval = delayTime; 
     dtimer.repeat = false; 
     dtimer.triggered.connect(cb); 
     dtimer.start(); 
    } 
} 

私は再びそれをクリックすると、出力は次のようになります。

qml: delayTimer is starting 
qml: here is console..... 
qml: 0.27777099609375 
qml: here is console..... 
qml: 0.407012939453125 
qml: here is console..... 
qml: 0.60552978515625 
qml: here is console..... 
qml: 0.360107421875 
qml: here is console..... 
qml: 0.21942138671875 
qml: here is console..... 
qml: 0.252288818359375 
qml: here is console..... 
qml: 0.88134765625 
qml: here is console..... 
qml: 0.63092041015625 
qml: here is console..... 
qml: 0.5125732421875 
+0

おそらく[Timer.triggeredOnStart](http://doc.qt.io/qt-5/qml-qtqml-timer.html#triggeredOnStart-prop)を 'false'に設定する必要があります。 – folibis

+0

@folibis:いいえ、デフォルトは 'false'です(あなたのリンクを参照してください) – derM

答えて

1

@のw1ck3dg0ph3rが指摘したように、あなたは信号を複数回に結合した1つの機能を持っています。しかし、QMLはすべてのスロットが同時に実行されると仮定しているため、QMLが最初に関数cbを実行することを決定すると、彼の解決策は失敗する可能性があります。

あり場所に置くいくつかの注意事項も、彼らはあなたがこの例では見ることができるようにではないが、あまりにも安全なように見えるかもしれません。それが、これは最初のクリックで無限ループになり

Button { 
    onClicked: { 
     clicked.connect(clicked) 
     console.log('here') 
    } 
} 

を接続は次回の実行でのみ実行され、同じ実行では実行されていないことが予想される場合があります。 - これではありません。ここ

Button { 
    onClicked: { 
     clicked.connect(function() {console.log('here'); clicked.connect(function() {console.log('there')})}); 
    } 
} 

あなたは両方の機能が最初の実行で実行されていることを、我々は上記学んだことから、期待するかもしれない、と出力がherethere次のとおりです。この例一方

(少なくとも私のマシンでは) シグナルのバインディングをシグナルの実行中に変更するときの動作はあまりよく定義されていません。

より良い解決策は、あなたの用途によって異なります。シグナルに結合された複数の機能を持たせたいのですか、それとも常にその機能だけにしたいのですか?

私は変数にあなたの機能を保存するためにreccomend、およびonClicked -eventで切断を処理したい:このよう

Button { 
    property var myCB 
    onClicked: { 
     delayTimer(delayTime, cb) { 
      if (myCB) dtimer.triggered.disconnect(myCB) 
      myCB = cb 
      dtimer.triggered.connect(myCB) 
      ... 
     } 
    } 
} 

あなたは切断が適切なタイミングで行われることを確保することができます。しかし、タイマーが他のソースによって再始動された場合でも、関数は依然としてバインドされています。これを望まない場合は、切断を確実にするために自己機能を持つ必要があります。テーラードソリューションを提供するために

、あなたはあなたのユースケースがあり、そしてあなたが期待する正確に何をどのように詳細を追加する必要があります。

6

あなたがスロットにあなたがdelayTimer()を呼び出すたびに、あなたの信号を接続しているので、接続が蓄積し、スロットがあります複数回呼び出されます。私はQML/JSに慣れていないんだけど、あなたはタイムアウトがトリガされた後のスロットを切断する必要があります。

function delayTimer(delayTime, cb) { 
    console.log("delayTimer is starting"); 
    dtimer.interval = delayTime; 
    dtimer.repeat = false; 
    dtimer.triggered.connect(cb); 
    dtimer.triggered.connect(function(){ 
     dtimer.triggered.disconnect(cb); 
    }); 
    dtimer.start(); 
} 
+0

これはすべての場合に有効です。AFAIK QMLは、信号に接続されているスロットを実行する際に、いかなる順序も保証しません。したがって、 'dtimer.triggered.disconnect(cb)'は 'cb'が実行される前に発生する可能性があります。 – derM

関連する問題