web-dev-qa-db-ja.com

QMLで遅延関数を作成する方法は?

QMLアプリケーションでjavascript行の実行の間に遅延を導入するために使用できるように、遅延に時間のパラメーターを取るJavaScriptで遅延関数を作成したいと思います。おそらく次のようになります。

_function delay(delayTime) {
// code to create delay
}
_

関数delay()の本体が必要です。 javascriptのsetTimeout()はQMLでは機能しないことに注意してください。

22

あなたの質問へのコメントで示唆されているように、 Timer コンポーネントはこれに対する良い解決策です。

function Timer() {
    return Qt.createQmlObject("import QtQuick 2.0; Timer {}", root);
}

timer = new Timer();
timer.interval = 1000;
timer.repeat = true;
timer.triggered.connect(function () {
    print("I'm triggered once every second");
})

timer.start();

上記は私が現在それをどのように使用しているかということであり、ここにあなたの質問の例を実装したかもしれません。

function delay(delayTime) {
    timer = new Timer();
    timer.interval = delayTime;
    timer.repeat = false;
    timer.start();
}

(何もしません;読んでください)

実装するために探している正確な方法は、プログラムの次の行が実行されるまでblockを探していることを示唆しています。ただし、JavaScriptは単一の実行スレッドでのみ実行されるため、プログラムでその他すべてをブロックするため、これを回避する方法としてはあまり適していません。

別の方法は、コールバックを渡すことです。

function delay(delayTime, cb) {
    timer = new Timer();
    timer.interval = delayTime;
    timer.repeat = false;
    timer.triggered.connect(cb);
    timer.start();
}

そのようにそれを使用することができます。

delay(1000, function() {
    print("I am called one second after I was started.");
});

それが役に立てば幸い!

編集:上記は、QMLファイルに後でインポートする別のJavaScriptファイルで作業していることを前提としています。 QMLファイルで直接同等のことを行うには、これを行うことができます。

import QtQuick 2.0

Rectangle {
    width: 800
    height: 600

    color: "brown"

    Timer {
        id: timer
    }

    function delay(delayTime, cb) {
        timer.interval = delayTime;
        timer.repeat = false;
        timer.triggered.connect(cb);
        timer.start();
    }

    Rectangle {
        id: rectangle
        color: "yellow"
        anchors.fill: parent
        anchors.margins: 100
        opacity: 0

        Behavior on opacity {
            NumberAnimation {
                duration: 500
            }
        }
    }

    Component.onCompleted: {
        print("I'm printed right away..")
        delay(1000, function() {
            print("And I'm printed after 1 second!")
            rectangle.opacity = 1
        })
    }
}

ただし、これが実際の問題の解決策だとは思いません。アニメーションを遅らせるには、 PauseAnimation を使用できます。

33
Marcus Ottosson

マーカスの答えは仕事をしますが、1つの大きな問題があります

問題は、一度トリガーされた後でも、コールバックがtriggered信号に接続し続けることです。これは、その遅延関数を再度使用すると、タイマーがトリガーすることを意味しますall以前に接続されたコールバック。そのため、トリガー後にコールバックを切断する必要があります。

これは遅延機能の私の拡張バージョンです:

Timer {
    id: timer
    function setTimeout(cb, delayTime) {
        timer.interval = delayTime;
        timer.repeat = false;
        timer.triggered.connect(cb);
        timer.triggered.connect(function release () {
            timer.triggered.disconnect(cb); // This is important
            timer.triggered.disconnect(release); // This is important as well
        });
        timer.start();
    }
}

...

timer.setTimeout(function(){ console.log("triggered"); }, 1000);
10
Bumsik Kim

Componentオブジェクトを使用してTimerオブジェクトを格納する別のバリ​​エーションがあります。

次に、setTimeoutのような関数を実装して、このTimerオブジェクトを動的に作成して呼び出します。

N.B.答えは、パラメーターショートカット、残りのパラメーター、およびスプレッド構文を利用するためのECMAScript 7(したがってECMAScript 6)を含むQt5.12.xを想定しています。

_    function setTimeout(func, interval, ...params) {
        return setTimeoutComponent.createObject(app, { func, interval, params})
    }

    function clearTimeout(timerObj) {
        timerObj.stop()
        timerObj.destroy()
    }

    Component {
        id: setTimeoutComponent
        Timer {
            property var func
            property var params
            running: true
            repeat: false
            onTriggered: {
                func(...params)
                destroy()
            }
        }
    }
_

次のスニペットでは、console.log(31, 32, 33)を今から0〜1000msの間のランダムな時間遅延で呼び出します。

_console.log("Started")
setTimeout(console.log, Math.floor(1000 * Math.random()), 31, 32, 33)_

参照: https://community.esri.com/groups/appstudio/blog/2019/05/22/ecmascript-7-settimeout-and-arrow-functions

1
Stephen Quan

qtTestを使用できます

import QtTest 1.0
import QtQuick 2.9

ApplicationWindow{
    id: window

    TestEvent {
        id: test
    }

    function delay_ms(delay_time) {
        test.mouseClick(window, 0, 0, Qt.NoButton, Qt.NoModifier, delay_time)
    }
}
0
fcying