このページでは

QMLおよびQt Quick

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

カスタム UI コントロールよりも組み込みコントロールを使用する

今日の世界において、スムーズでモダンな UI はあらゆるアプリケーションの成功の鍵であり、その点で QML はデザイナーや開発者にとって非常に理にかなっています。Qt は、スムーズでモダンな外観の UI を作成するために必要な、最も基本的な UI コントロールを提供しています。独自のカスタム UI コントロールを作成する前に、この UI コントロールのリストを確認することをお勧めします。

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

Qt Design Studio でUIを設計する際、これらのコントロールを使用できます。さらに、アプリケーションのプロトタイピング用に、タイムラインベースのアニメーション、視覚効果、レイアウト、およびライブプレビュー機能も提供されています。

コーディング規約

「QML コーディング規約」を参照してください。

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

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

たとえば、C++プロジェクトの場合、次のようなディレクトリ構造を想定します。

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ファイルは、自動的に事前コンパイルされます。

qt_add_qml_module を使用する場合は、QML ファイルを CMakeLists.txtと同じディレクトリに配置する必要があります。そうしないと、それらの暗黙的なインポートが、それらが属するQML モジュールとは異なるものになってしまいます。これはよくあるミスの原因です。

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

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

  • 宣言型言語は、UIの定義に非常に適しています。
  • QMLコードは、C++よりも記述が簡潔で、強タイプではないため、記述が容易です。この特性により、プロトタイピングに最適な言語となっており、例えばデザイナーとの共同作業において不可欠な利点となります。
  • QMLでは、イベントに応答するためにJavaScriptを容易に利用できます。

C++ などの強タイプ言語は、アプリケーションのビジネスロジック、つまりバックエンドに最適です。通常、このようなコードは複雑な計算やデータ処理などのタスクを実行しますが、強タイプ言語では QML よりも高速に処理できます。

Qtでは、アプリケーション内でQMLと強型付け言語を統合するためのさまざまなアプローチが用意されています。典型的なユースケースとして、ユーザーインターフェースにデータの一覧を表示する場合が挙げられます。データセットが静的で単純かつ小規模な場合は、QMLで記述されたモデルで十分です。

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

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

model: 10

より大規模で動的なデータセットの場合は、C++などの強型言語を使用してビジネスロジックを処理します。

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

QMLのリファクタリングはC++のリファクタリングよりもはるかに容易であるため、メンテナンスを容易にするためには、C++の型がQMLを意識しないように努めるべきです。これは、C++の型への参照をQML側に「押し込む」ことで実現できます。

これを行うには、必須プロパティを使用し、QQmlApplicationEngine::setInitialProperties を介して設定します。また、C++側がQMLに提供したいすべてのデータを返す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 Quick ビューの使用

モデルへの状態の保存

「Avoid Storing State in Delegates 」を参照してください。

Qt Quick レイアウトの使用

Qt XMLでは、Qt Quick のアイテムをレイアウト上で視覚的に配置するための「Qt Quick 」レイアウトが提供されています。代替手段であるアイテムポジショナーとは異なり、「Qt Quick 」レイアウトでは、ウィンドウのサイズ変更時に子要素のサイズも変更できます。多くのユースケースでは「Qt Quick 」レイアウトが推奨されますが、使用する際には以下の「すべきこと」と「すべきでないこと」を考慮する必要があります:

推奨事項

  • anchors 、またはwidth およびheight プロパティを使用して、レイアウト以外の親アイテムに対するレイアウトのサイズを指定します。
  • Layout アタッチドプロパティを使用して、レイアウトの直下の子要素のサイズおよび配置属性を設定します。

避けるべきこと

  • implicitWidth および implicitHeight を提供するアイテムについては、その暗黙的なサイズが不十分な場合を除き、推奨サイズを定義しないでください。
  • レイアウトの直子であるアイテムに対してアンカーを使用しないでください。代わりに、Layout.preferredWidth およびLayout.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
            }
        }
    }

注:レイアウトと アンカーは 、いずれもメモリとインスタンス化に時間を要するオブジェクトの一種です。x、y、width、height プロパティへの単純なバインディングで十分な場合は、これら(特にリストやテーブルのデリゲート、およびコントロールのスタイル内)での使用を避けてください。

型安全性

QMLでプロパティを宣言する際、「var」型を使用すると簡単で便利です:

property var name
property var size
property var optionsMenu

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

  • 型が間違った値が代入された場合、報告されるエラーは、プロパティが代入された場所ではなく、プロパティの宣言場所を指してしまいます。これにより、エラーの追跡が困難になり、開発プロセスが遅延します。
  • 上記のようなエラーを検出するための静的解析は不可能です。
  • プロパティの実際の基底型が、読者にとって常に一目でわかるわけではありません。

その代わりに、可能な限り常に実際の型を使用してください:

property string name
property int size
property MyMenu optionsMenu

プロパティの変更シグナル

微妙なバグを回避するため、値変更シグナルよりも明示的な相互作用シグナルの使用を優先してください。

valueChanged を使用すると、何らかの理由で値が丸められ거나正規化されることにより、値が絶えず変化するイベントの連鎖が発生する可能性があります。

明示的な相互作用シグナルのみを使用すれば、この種の問題をすべて回避できます。

たとえば、Slider には、moved やvalueChanged といった類似のシグナルがあります。

Slider {
    value: someValueFromBackend

    onValueChanged: pushToBackend(value)
    // or
    onMoved: pushToBackend(value)
}

どちらの場合も見た目は似ており、valueChanged を使いたくなるかもしれません。

開発者は、Slider が、例えば最小値や最大値へのクリッピングや丸め処理などの理由で、自動的に値を変更し得るという事実を見落としがちです。この場合、valueChanged シグナルが発行されます。valueChanged シグナルを使用すると、予期しないタイミングで発行されることに気づくかもしれません。

このような問題を回避するには、インタラクション信号(ユーザーがコントロールとやり取りした際に発火する信号)を使用してください。この例では、moved 信号を使用する場合、ユーザーがコントロールを変更したときにのみスロットがトリガーされます。

パフォーマンス

QMLおよびQt Quick のパフォーマンスに関する詳細については、「QMLのパフォーマンスに関する考慮事項と推奨事項」を参照してください。

命令型代入よりも宣言型バインディングを優先する

QML では、入力イベントへの応答やネットワーク経由でのデータ送信などのタスクを実行するために、命令型の JavaScript コードを使用することが可能です。命令型コードは QML において重要な役割を果たしていますが、それを使用すべきでない場面を認識しておくことも重要です。

たとえば、次のような命令型の代入を考えてみましょう。

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

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

  • 処理が遅い。color プロパティは、まずデフォルトの初期化値で評価され、その後で「red」で再度評価される。
  • ビルド時に検出できるはずのエラーが実行時まで先送りされ、開発プロセスの速度が低下します。
  • 既存の宣言型バインディングを上書きしてしまいます。ほとんどの場合、これは意図された動作ですが、意図しない場合もあります。詳細については、「バインディングの上書きのデバッグ」を参照してください。
  • ツールとの互換性に問題が生じます。例えば、Qt Quick DesignerはJavaScriptをサポートしていません。

代わりに、コードを宣言型バインディングとして書き直すことができます:

Rectangle {
    color: "red"
}

デリゲートに状態を保存しないでください

デリゲート内に状態を保存しないでください。ここでの問題は、デリゲートが何度も生成・破棄されるため、保存された状態が失われてしまうことです。

// Wrong approach:
ListView {
    // ...

    delegate: Button {
        // ...
        property bool someStateProperty
        onClicked: someStateProperty = true
    }
}

代わりに、デリゲートの外側(例えばモデル内)に状態を保存してください。そうすれば、デリゲートが破棄されても、保存された状態が失われることはありません。

// Right approach:
ListView {
    // ...

    delegate: Button {
        // ...
        onClicked: model.someStateProperty = true
    }
}

ユーザー向けの文字列は翻訳可能にする

ユーザー向けの文字列は、最初から翻訳可能にすることをお勧めします。「翻訳のためのソースコードの記述」を参照してください。

ToolButton {
    id: selectionToolButton
    // ...
    icon.source: "qrc:/images/selection.png"

    Tooltip.Text: qsTr("Select pixels within an area and move them")

    onClicked: canvas.tool = ImageCanvas.SelectionTool
}

ネイティブスタイルをカスタマイズしない

ネイティブスタイル(Windows および macOS のスタイル)はカスタマイズに対応していません。ネイティブスタイルをカスタマイズしないようにしてください。

// Wrong approach:
import QtQuick.Controls.Windows

// Don't customize a native style
Button {
    background: Rectangle { /*...*/ }
}

その代わりに、カスタマイズしたコントロールは、常にすべてのプラットフォームで利用可能な単一のスタイル(Basic Style、Fusion Style、Imagine Style、Material Style、Universal Styleなど)を基にすることを推奨します。そうすることで、アプリケーションがどのスタイルで実行されても、常に同じ外観になることが保証されます。 別のスタイルの使用方法については、「 Qt Quick コントロールでのスタイルの使用」を参照してください。あるいは、独自のスタイルを作成することもできます。

// Right approach:
import QtQuick.Controls.Basic

// You can customize a commonly available style
Button {
    background: Rectangle { /*...*/ }
}

ツールとユーティリティ

QML やQt Quick の作業を容易にする便利なツールやユーティリティについては、「Qt Quick のツールとユーティリティ」を参照してください。

シーングラフ

Qt Quick のシーングラフに関する詳細については、「Qt Quick のシーングラフ」を参照してください。

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

ディスプレイの解像度が向上するにつれ、スケーラブルなアプリケーション UI の重要性はますます高まっています。これを実現するアプローチの一つとして、異なる画面解像度に対応した UI のコピーを複数用意し、利用可能な解像度に応じて適切なもの読み込む方法があります。これはかなりうまく機能しますが、メンテナンスの負担が増加します。

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

  • ビジュアルアイテムの配置には、アンカーまたはQt Quick のレイアウトモジュールを使用してください。
  • ビジュアルアイテムに対して、幅や高さを明示的に指定しないでください。
  • アプリケーションがサポートする各ディスプレイ解像度に対応した画像やアイコンなどのUIリソースを用意してください。Qt Quick の「Controls gallery」サンプルは、@2x 、@3x 、@4x の各解像度に対応したqt-logo.png を提供することで、この点を見事に実証しており、アプリケーションが高解像度ディスプレイに対応できるようになっています。高DPIスケーリング機能が明示的に有効になっている場合、Qtは指定されたディスプレイに適した画像を自動的に選択します。
  • 小さなアイコンにはSVG画像を使用してください。大きなSVGはレンダリングに時間がかかる場合がありますが、小さなものは問題なく動作します。ベクター画像を使用すれば、ビットマップ画像のように複数のバージョンの画像を用意する必要がなくなります。
  • Font Awesomeなどのフォントベースのアイコンを使用してください。これらはあらゆるディスプレイ解像度に合わせて拡大縮小され、色付けも可能です。「Qt Quick Controls Text Editor」の例が、これをよく示しています。

これらを実装すれば、アプリケーションの UI は、利用可能なディスプレイの解像度に応じて適切にスケーリングされるはずです。

Qtロゴが入ったギャラリーのウェルカム画面の例

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.