QMLとQt Quickのベストプラクティス

QML と Qt Quick は多くの利点がありますが、状況によっては難しいこともあります。以下のセクションでは、アプリケーションを開発する際に、より良い結果を得るためのベストプラクティスについて詳しく説明します。

カスタムUIコントロール

流動的でモダンな UI は、今日の世界でアプリケーションを成功させるための鍵です。Qtは、流動的でモダンなUIを作成するために必要な、最も基本的なUIコントロールを提供しています。独自のUIコントロールを作成する前に、このUIコントロールのリストを参照することをお勧めします。

Qt Quick自体が提供するこれらの基本的なUIコントロールに加えて、Qt Quick Controlsには豊富なUIコントロールのセットも用意されています。これらは最も一般的なユースケースにそのまま対応し、カスタマイズオプションでより多くの可能性を提供します。特に、Qt Quick Controls は最新の UI デザイントレンドに沿ったスタイリングオプションを提供します。これらのUIコントロールがアプリケーションのニーズを満たさない場合は、カスタムコントロールを作成することをお勧めします。

このコントロールは、Qt Design Studio で UI をデザインするときに使用できます。さらに、タイムラインベースのアニメーション、視覚効果、レイアウト、アプリケーションのプロトタイピングのためのライブプレビューを提供します。

コーディング規約

QML Coding Conventions を参照してください。

アプリケーションリソースのバンドル

ほとんどのアプリケーションは、リッチなユーザーエクスペリエンスを提供するために、画像やアイコンのようなリソースに依存しています。これらのリソースを、ターゲットOSに関係なくアプリケーションで利用できるようにすることは、しばしば課題となります。一般的なOSの多くは、ファイルシステムへのアクセスを制限する厳格なセキュリティポリシーを採用しているため、これらのリソースをロードすることが難しくなっています。その代替として、Qt はアプリケーション・バイナリに組み込まれた独自のリソース・システムを提供し、ターゲット OS に関係なくアプリケーションのリソースにアクセスできるようにします。

例えば、次のようなプロジェクトのディレクトリ構造を考えてみましょう:

MyModule
├── images
│   ├── image1.png
│   └── image2.png
├── CMakeLists.txt
└── main.qml

この構造をCMake QMLモジュールとして表現すると、次のようになります:

qt_add_qml_module(my_module
   URI MyModule
   VERSION 1.0
   QML_FILES
       main.qml
   RESOURCES
       images/image1.png
       images/image2.png
   # ...
)

QML_FILES の下にリストされている全ての QML ファイルは、事前に自動的にコンパイルされます。

QMLファイルはCMakeLists.txtのqt_add_qml_moduleと同じディレクトリに置いてください。そうしないと、暗黙のインポートが所属するQML モジュールと異なってしまいます。これはよくある間違いの原因です。

UI とビジネスロジックの分離

ほとんどのアプリケーション開発者が達成したい重要な目標の1つは、保守性の高いアプリケーションを作ることです。この目標を達成する方法の一つは、ユーザーインターフェースをビジネスロジックから分離することです。以下に、アプリケーションのUIをQMLで記述すべきいくつかの理由を示します:

  • 宣言型言語はUIの定義に適している。
  • QML のコードは C++ よりも冗長でなく、強く型付けされていないため、書くのが簡単です。そのため、プロトタイプを作成するのに適した言語であり、デザイナーと共同作業をする際などには欠かせない言語です。
  • JavaScriptはQMLの中で、イベントへの応答に簡単に使うことができます。

強く型付けされた言語であるC++は、アプリケーションのビジネスロジックに 最適です。一般的に、このようなコードは複雑な計算やデータ処理のようなタスクを実行するため、QML よりも C++ の方が高速です。

Qtでは、QMLとC++のコードをアプリケーションに統合するための様々なアプローチを提供しています。典型的なユースケースは、ユーザーインターフェースにデータのリストを表示することです。データセットが静的で、単純で、かつ/または小さい場合、QMLで書かれたモデルで十分です。

以下のスニペットはQMLで書かれたモデルの例を示しています:

model: [ "Item 1", "Item 2", "Item 3" ]

model: 10

大規模であったり、頻繁に変更されるような動的なデータセットにはC++を使用してください。

C++からQMLへのデータ公開

QMLのリファクタリングは、C++のリファクタリングよりもずっと簡単です。したがって、メンテナンスの手間を省くためには、C++の型をできるだけQMLに意識させないようにすべきです。これは、C++の型への参照をQMLに「プッシュ」することで実現できます。

そのためには、必須プロパティを使用し、QQmlApplicationEngine::setInitialProperties で設定します。また、C++側がQMLに提供したいすべてのデータを返すsingletons を1つまたは複数作成することも可能です。

この方法では、将来QMLのリファクタリングが必要になってもC++は変更されません。

C++の型をQMLに公開する正しい方法を選択するためのクイックガイドについては、C++とQMLの正しい統合方法を選択するを参照してください。

Qt Design Studio を使う

Qt Design Studio では、.ui.qml という拡張子を持つ UI ファイルを使用して、UI の視覚的な部分と、.qmlファイルで実装する UI ロジックを分けています。UI ファイルの編集は、Qt Design Studio の2D ビューでのみ行ってください。Qt Design Studio がサポートしていないコードを他のツールで追加すると、エラーメッセージが表示されます。エラーを修正して、UI ファイルの視覚的な編集を可能にしてください。通常、サポートされていないコードは.qmlファイルに移動する必要があります。

Qt クイックレイアウトを使う

Qt では、Qt Quick アイテムを視覚的にレイアウトするための Qt Quick Layouts を提供しています。Qtクイックレイアウトは、アイテムポジショナーとは異なり、ウィンドウのリサイズ時に子アイテムのサイズを変更することができます。Qtクイックレイアウトは、ほとんどの使用例において望ましい選択ですが、使用する際には以下の注意 点を考慮する必要があります:

注意点

  • anchors またはwidthheight プロパティを使用して、レイアウト以外の親アイテムに対するレイアウトのサイズを指定します。
  • Layout attachedプロパティを使用して、レイアウトの直接の子のサイズと配置属性を設定する。

注意点

  • implicitWidthとimplicitHeightを提供するアイテムには、その暗黙のサイズが満足できない場合を除き、優先サイズを定義しないでください。
  • レイアウトの直属の子であるアイテムにアンカーを使わない。代わりにLayout.preferredWidthLayout.preferredHeight を使用してください:
    RowLayout {
        id: layout
        anchors.fill: parent
        spacing: 6
        Rectangle {
            color: 'orange'
            Layout.fillWidth: true
            Layout.minimumWidth: 50
            Layout.preferredWidth: 100
            Layout.maximumWidth: 300
            Layout.minimumHeight: 150
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
        Rectangle {
            color: 'plum'
            Layout.fillWidth: true
            Layout.minimumWidth: 100
            Layout.preferredWidth: 200
            Layout.preferredHeight: 100
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
    }

Note: レイアウトとアンカーは、どちらもメモリとインスタンス生成に時間がかかるタイプのオブジェクトです。x、y、width、heightプロパティへの単純なバインディングで十分な場合は、(特にリストやテーブルのデリゲート、コントロールのスタイルでは)使用を避けてください。

型の安全性

QMLでプロパティを宣言する場合、"var "型を使うのが簡単で便利です:

property var name
property var size
property var optionsMenu

しかし、この方法にはいくつかの欠点があります:

  • 間違った型の値が代入された場合、報告されるエラーはプロパティが代入された場所ではなく、プロパティを宣言した場所を指します。このため、エラーを追跡することが難しくなり、開発プロセスが遅くなります。
  • 上記のようなエラーを発見するための静的解析は不可能です。
  • プロパティの実際の基本型は、読み手にとって必ずしもすぐに明確になるとは限りません。

代わりに、可能な限り常に実際の型を使用します:

property string name
property int size
property MyMenu optionsMenu

パフォーマンス

QMLとQt Quickのパフォーマンスに関する情報は、QML Performance Considerations and Suggestionsを参照してください。

宣言的なバインディングを優先する

QMLでは、入力イベントへの応答やネットワーク経由でのデータ送信などのタスクを、命令型のJavaScriptコードで実行することが可能です。QMLにおいて命令型コードは重要な位置を占めていますが、同時に、命令型コードを 使ってはいけない場面も認識しておく必要があります。

例えば、次のような命令的な代入を考えてみましょう:

Rectangle {
    Component.onCompleted: color = "red"
}

これには次のような欠点があります:

  • 遅い。colorプロパティは、まずデフォルトの値で評価され、後でもう一度 "red "で評価されます。
  • ビルド時に発見される可能性のあるエラーを実行時に遅らせ、開発プロセスを遅くする。
  • 宣言的バインディングを上書きしてしまう。ほとんどの場合、これは意図的なものですが、意図しない場合もあります。詳しくはバインディングの上書きのデバッグを参照してください。
  • 例えば Qt Quick Designer は JavaScript をサポートしていません。

代わりに宣言型バインディングに書き換えることができます:

Rectangle {
    color: "red"
}

ツールとユーティリティ

QML や Qt Quick をより使いやすくする便利なツールやユーティリティについては、Qt Quick Tools and Utilities を参照してください。

シーングラフ

Qt Quick のシーングラフについては、Qt Quick Scene Graph を参照してください。

スケーラブルなユーザーインターフェース

ディスプレイの解像度が向上するにつれて、スケーラブルなアプリケーション UI がますます重要になります。これを実現するアプローチの1つは、異なる画面解像度用にUIのコピーを複数保持し、利用可能な解像度に応じて適切なものをロードすることです。これはかなりうまくいきますが、メンテナンスのオーバーヘッドが増えます。

Qtはこの問題に対してより良い解決策を提供しており、アプリケーション開発者は以下のヒントに従うことを推奨します:

  • ビジュアルアイテムのレイアウトには、アンカーか Qt Quick Layouts モジュールを使う。
  • ビジュアルアイテムの幅と高さを明示的に指定しない。
  • アプリケーションがサポートするディスプレイ解像度ごとに、画像やアイコンのようなUIリソースを用意する。Qt Quick Controls ギャラリーの例では、@2x@3x@4x の解像度に対応したqt-logo.png を提供することで、高解像度ディスプレイにも対応できるようにしています。Qtは、高DPIスケーリング機能が明示的に有効になっていれば、指定されたディスプレイに適した適切な画像を自動的に選択します。
  • 小さなアイコンには SVG 画像を使用します。大きな SVG はレンダリングに時間がかかりますが、小さな SVG はうまく機能します。ベクター画像は、ビットマップ画像で必要なように、画像の複数のバージョンを提供する必要性を回避します。
  • Font Awesomeなどのフォントベースのアイコンを使いましょう。これらのアイコンは、どのようなディスプレイ解像度にも対応し、カラー化も可能です。Qt Quick Controls Text Editorの例が、これをよく示しています。

このようにして、アプリケーションのUIはディスプレイの解像度に応じて拡大縮小できるようになります。

©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。