QML での Rectangle{} のデバッグ。printf() と同様ですが、QT 用です。

最近、私は Rectangle{} と名付けることにした QT/QML のデバッグ技術を使用しています。 デバッグ、printf() と同じ流れで デバッグ。 QML は HTML/CSS のようなマークアップ言語 (QT フレームワークの一部) であり、(QT) アプリケーションの C++ コードと対話できる JavaScript 内にあります。 QML には anchors の概念があります 要素の相対的な配置。全体で、anchors 非常にうまく機能しますが、継承と複雑なレイアウトが作用すると複雑になる可能性があります。 Rectangle{} デバッグのスタイルは、要素の周囲に境界線のある半透明の長方形を配置するため、配置を視覚化し、変更がどのような影響を与えるかを確認できます。この記事では、実際に printf() を実行するためのヒントを含め、最近、このスタイルのデバッグをコーヒー マシンのユーザー インターフェイスに適用した例を示します。 スタイルのデバッグ (ただし Console.log を使用) ).

以前に QT / QML について書いたことがあります。その記事では、C++ と QML の間で通信する方法であるシグナルとスロットについて説明しました。

Qt Quick アンカー システムを使用すると、異なるアイテムのアンカー ライン間の関係を定義できます。たとえば、次のように書くことができます:

Rectangle { id: rect1; ... }
Rectangle { id: rect2; anchors.left: rect1.right; ... }

この場合、 rect2 の左端 rect1 の右端にバインドされています 、以下を生成します:

前述のように、特にアンカー/位置が C++ 側からのシグナルを介して入ってくる動的変数に依存する場合、これはすぐに複雑になります。プラットフォーム固有の制限により、QT Design Studio も私たちのプロジェクトでは使用できません。

printf() とは デバッグ? ubiquitousC 機能にちなんで名付けられた手法です。プログラム フローの重要なポイントで多かれ少なかれ慎重に選択されたステータス情報を出力するコマンドを挿入し、その情報を観察し、その情報に基づいて問題を推測することによって行われるデバッグ作業を説明するために使用されます。

私は専用のデバッガーを好みますが、IDE に統合された優れたものでなければなりません。 CLionにはこれがあり、Visual Studioには妥当なものがあり、QT CreatorのQMLデバッガーはただ悪い.

QML のような視覚要素の場合、配置や相対的なものをデバッグするのは難しくなります。それに加えて、QT Creator には QML デバッガーがありますが、これを使うのはひどいものです。この長方形のトリックを使用すると、要素、境界、および変更が非常に目に見えるようになります。オブジェクトを中央に配置するには、anchors.centerIn: parent を使用しますか? または anchors.horizontalCenter: parent.horizontalCenter ?変更の周りに大きな四角形があると、変更が何をするかがより分かりやすくなります。

Rectangle{} のデバッグ

最近、QT を使用するマシンのユーザー インターフェイスの 1 つにタッチレス コーヒー機能を実装する必要がありました。 QML コントロールは既に存在していましたが、設定に応じて条件付きで別の要素を置き換えて、いくつかの画面に配置する必要がありました。コントロールをその他の要素に配置しようとした最初の試みは、小さな、中央に配置されていない要素になりました。以下は、左側が最初の試行、右側が最終結果を示す画像です:

スクリーンショットがぼやけているのは、サイトに合わせてサイズを変更したためです。マシン上では非常に鮮明です。

条件付きで置き換えられた要素がサイズ変更されて中央に配置され、QMLsyntax がコピーされ、予期しない結果になりました。私が最初にしたことは、コンテナの周りに四角形を置き、何が起こっているかを視覚化することでした:

Rectangle {
    anchors.fill: parent
    color: "#ffffff"
    visible: true
    opacity: 0.8
    border.color: "#ff0000"

    //insert your objects here
}

次のようになります:

ご覧のとおり、新しい qr 画像は正確に左上隅にあるわけではないため、QR コントロール内で何らかの配置が行われています。別のRectangleを入れましょう QR コード コントロールで、それが何をしているかを確認します。今回は、外側のコンテナと区別するために背景色を明るいオレンジ色にしています:

QR コントロール内のサイズも期待どおりではありません。センタリングは正しいです。特定のコントロールが他の UI で既に使用されており、正しく機能していることを覚えておいてください。 Image.Fillmode をいじってみましょう 、 Pad またはPreserveAspectFit いくつかの anchors.fill: parent と同様に、トリックを実行する必要があります あちこちに散らばっています:

ご覧のとおり、Code: はほぼそこにあります。 テキストは両方のコントロールの外にあります。それは anchor.top: qrimage.bottom を持っています 、これは正しいですが、このコントロールがトリミングされると、テキストが表示されなくなります。この Rectangle{} を使用していなかったら デバッグ方法に気づけなかったので、将来バグを引き起こす可能性があります。

Image.width: ### * 0.85 でテストしてみましょう :

より良いですが、コントロールが大きくても、まだ正しくなく、下部のスペースが多すぎます。それを修正することは、この記事の範囲外です。コントロールを中央に配置して続行します。それは anchors.fill: parent の正しい組み合わせの場合でした と anchors.horizontalCenter: parent.horizontalCenter いくつかのコントロールで。詳細は省きますが、数分後に正しいコンボを見つけました:

残された唯一のことは、長方形を削除して (または、さらに悪いことに、それらを透明にして)、機能を完成させることです。

長方形のデバッグ手法がなければ、テキストが画像の外側にあることに気付かなかったでしょう。または、コントロールが正確に中央にあるかどうかについての議論があります。この場合、デバッガーをじっと見つめるよりも、視覚的に見えるようにする方がはるかに役に立ちます。

ご参考までに、QR コードをスキャンした後の Web ページは次のようになります。

この特定の QR コードは、開発環境でのみアクティブだったため機能しませんでしたが、コードをスキャンするとどうなるか疑問に思われるかもしれません。すべてのマシンの消費量を含む Web ページが表示され、1 つを選択し、飲み物をカスタマイズして [注文] を押します。ユーザーが画面に触れることなく、機械が生産を開始します。バックエンドで MQTT を使用し、月間データ使用量が 7 MBa 未満で、応答性が高く、開発が非常にクールです。しかし、それは別の日の話です。

Console.log QML デバッグ

QML はマークアップ言語とインライン JavaScript を組み合わせているため、私の場合はデバッグ時に役立ちます。たとえば、要素の可視性は、QML プロパティによって、または C++ シグナルとスロットによって決定できます。 visible: varName を置き換えることによって JavaScript 関数呼び出しを使用すると、値をコンソールに記録できます。そうすることで、要素が非表示であるが表示されるべきである場合、そのブール値を除外できます。スタイル (たとえば、z-index) が返された実際の値の発行者であるかどうかを判断するのに役立ちます。

以下は QML ファイルの例です:

Item {
  function logAndReturnValue(varToLog)
  {
    console.log("value: " + varToLog);
    return varToLog;
  }
  property bool varName: false;

  Text {
    visible: logAndReturnValue(varName)
    text: "Example Text"
  }
}

この単純なサンプル関数は、変数を受け取り、それをコンソールに記録し、結果を返します。Text 要素には visible: という行があります 、これは boolean です 値 true または false、またはブール値を含む別の変数またはブール値を返す関数。シグナルを使用することで、C++ コードでこれを設定できます。そのしくみについては、私の他の例の記事を参照してください。

事実上、 visible: varName と書くことができます 、しかし、このロギング方法では、それも印刷されます。

このメソッドを使用するほかに、 Component.onCompleted にフックすることもできます オブジェクトがインスタンス化された後に発行されるシグナルハンドラ:

Text {
    Component.onCompleted: console.log("Text onCompleted.")
    text: "Example Text"
}

私の経験では、QML デバッガーは操作が面倒で、CLion の GDB 統合ほど洗練されていません。また、結果を更新しない、正しくステップオーバーしない、あらゆる種類の小さな問題など、少し奇妙です。 QT Creator とその QML デバッガーがいかに悪いかという理由で、QML でのこの printf スタイルのデバッグを好むことがよくあります。