JavaScript 割り当て後に Qt/QML プロパティ バインディングが壊れる

プロパティ バインディングは、Qt/QML で最も強力な概念の 1 つです。プロパティ バインディングを使用すると、さまざまなオブジェクト プロパティ間の関係を指定できます。プロパティの依存関係の値が変化すると、指定された関係に従ってプロパティが自動的に更新されます。 QML エンジンは、プロパティの依存関係 (つまり、バインディング式の変数) を監視します。変更が検出されると、QML エンジンはバインド式を再評価し、新しい結果をプロパティに適用します。 )。この投稿では、さまざまな動作と 13 の使用方法を示します JavaScript を介してプロパティ バインディングを割り当てます。

この動作は意図的であり、文書化されており、意図的にプロパティ バインディングを解除したい場合に役立つことに注意してください。

この投稿は、何が起こっているのかを知らないと混乱する可能性があるため、さまざまな動作を知らせることを目的としています.私の同僚はバグに取り組んでいましたが、彼はこの動作に気づいておらず、それが根本的な問題であることを理解するのに 2 時間かかりました。デバッグ セッションに深く入り込んでいるときに、私にも起こる可能性があります。

デモンストレーション

上の画像は問題を示しています。

トップ 25 (32 ) 41 プロパティは 59 にバインドされています (66 ) 72 プロパティであるため、テキストを編集すると、ボタンのテキストが自動的に更新されます。

2 番目のボタンは、86 で JavaScript の割り当てを行うことにより、バインディングを解除します。 関数:

onClicked: boundButton.text = "Binding broken"

ボタンをクリックして 98 のテキストを変更した場合 、ボタンのテキストは、入力したテキストを反映しなくなりました。

最後のボタンは、101 を使用してプロパティ バインディングを復元します。 関数:

onClicked: boundButton.text = Qt.binding(function () {
            return bindableTextField.text
        })
    }

少し複雑な構文ですが、仕事は完了します。

Qt.binding()

ドキュメントには次のように記載されています:

紛らわしいことに、そのページには最初の使用例ではなく、2 番目の使用例の例があります。より簡単な例は、別のドキュメント ページにあり、以下に転写されています:

以下の Rectangle は、最初にその高さが常に 117 の 2 倍であることを保証します。 .ただし、スペース キーを押すと、121 の現在の値 静的な値として高さに割り当てられます .その後、幅が変更されても、高さはこの値に固定されたままになります。静的値の割り当てにより、バインディングが削除されます。

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = width * 3
    }
}

長方形に固定の高さを与え、自動更新を停止することが意図されている場合、これは問題ではありません。ただし、幅と高さの間に新しい関係を確立することが意図されている場合は、新しいバインディング式を 138 でラップする必要があります。 代わりに関数を使用してください:

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = Qt.binding(function() { return width * 3 })
    }
}

これで、スペース キーが押された後、四角形の高さが常にその幅の 3 倍になるように自動更新され続けます。

もう 1 つの使用例は、私の経験では、あまり使用されていないか、少なくとも私が取り組んだプロジェクトでは使用されていません。 QML オブジェクトを動的に作成するのは最初は楽しいですが、型の安全性が失われ、すべて文字列であるため、最初は 1 つの名前を変更しても、別の場所で実行時エラーが発生するまで問題なく動作します。コンパイル時の安全性に甘んじているのかもしれませんが、そのような小さなタイプミスや名前の変更が、私が認めたい以上に私を悩ませました。一方、C++ では、もはやコンパイルされません。