スケーラビリティ

複数の異なるモバイル・デバイス・プラットフォーム向けにアプリケーションを開発する場合、次のような課題に直面します:

  • モバイル・デバイス・プラットフォームは、サイズ、アスペクト比、向き、密度など、さまざまな画面構成のデバイスをサポートしています。
  • プラットフォームによって UI の規約が異なるため、それぞれのプラットフォームでユーザーの期待に応える必要があります。

Qt Quick を使用すると、タブレットや携帯電話など、異なるタイプのデバイスで動作するアプリケーションを開発できます。特に、異なる画面構成に対応することができます。しかし、各ターゲットプラットフォームで最適なユーザーエクスペリエンスを実現するためには、常にある程度の修正と研磨が必要です。

スケーラビリティを考慮する必要があるのは、次のような場合です:

  • AndroidとiOSのような複数のデバイスプラットフォームや、複数のデバイスの画面構成にアプリケーションをデプロイしたい場合。
  • 最初のデプロイ後に登場するかもしれない新しいデバイスに備えたい場合。

Qt Quick を使用してスケーラブルなアプリケーションを実装するには、次の手順に従います:

  • UI コントロールのセットを提供するQt Quick Controls を使用して UI を設計します。
  • アイテムのサイズを変更できるQt Quick Layouts を使ってレイアウトを定義する。
  • プロパティ・バインディングを使用して、レイアウトではカバーできないユースケースを実装します。例えば、ピクセル密度が低い画面と高い画面で画像の別バージョンを表示したり、現在の画面の向きに応じてビューの内容を自動的に適応させたりできます。
  • 参照デバイスを選択し、実際の画面サイズに合わせて画像やフォントのサイズ、余白を調整するための拡大縮小率を計算します。
  • ファイルセレクタを使用して、プラットフォーム固有のアセットをロード。
  • ローダーを使用して、コンポーネントをオンデマンドでロードする。

アプリケーションを設計する際には、以下のパターンを考慮してください:

  • ビューのコンテンツは、どの画面サイズでもよく似ていますが、コンテンツ領域が拡張されている場合があります。Qt Quick ControlsのApplicationWindow QMLタイプを使用すると、コンテンツアイテムのサイズに基づいてウィンドウサイズが自動的に計算されます。Qtクイックレイアウトを使用してコンテンツアイテムを配置すると、Qtクイックレイアウトにプッシュされたアイテムのサイズが自動的に変更されます。
  • 小さなデバイスのページ全体のコンテンツは、大きなデバイスのレイアウトのコンポーネント要素を形成する可能性があります。そのため、そのコンポーネントを別のコンポーネント(つまり、別のQMLファイルで定義)とし、小さなデバイスでは、ビューに単にそのコンポーネントのインスタンスが含まれるようにすることを検討してください。より大きなデバイスでは、ローダーを使って追加項目を表示するのに十分なスペースがあるかもしれません。例えば、メールビューアの場合、画面が十分に大きければ、メールリストビューとメールリーダービューを並べて表示することができます。
  • ゲームの場合、通常、大きな画面のプレーヤーに不公平な利点を与えないように、拡大縮小しないゲームボードを作成したいと思うでしょう。1つの解決策は、サポートされている最小のアスペクト比(通常、3:2)のスクリーンに適合するセーフゾーンを定義し、4:3または16:9のスクリーンでは非表示になるスペースに装飾のみのコンテンツを追加することです。

アプリケーションウィンドウのサイズを動的に変更する

Qt Quick Controlsは、Qt Quick でユーザーインターフェースを作成するための UI コントロールのセットを提供します。通常、ApplicationWindow コントロールをアプリケーションのルート・アイテムとして宣言します。ApplicationWindow は、MenuBarToolBar 、StatusBar などの他のコントロールをプラットフォームに依存しない方法で配置するための利便性を提供します。ApplicationWindow は、実際のウィンドウの効果的なサイズ制約を計算するときに、コンテンツ項目のサイズ制約を入力として使用します。

アプリケーション・ウィンドウの標準的な部分を定義するコントロールに加えて、ビューやメニューの作成、ユーザーからの入力の提示や受信のためのコントロールも提供されています。Qt Quick Controls Stylesを使用すると、定義済みのコントロールにカスタムのスタイルを適用できます。

ToolBar のような Qt Quick Controls は、独自のレイアウトを提供しません。これには、Qt Quick Layouts を使用します。

画面コントロールを動的にレイアウトする

Qt クイックレイアウトではRowLayoutColumnLayoutGridLayout の QML タイプを使用して、スクリーンコントロールを行、列、またはグリッドにレイアウトする方法を提供します。これらの QML タイプのプロパティは、レイアウトの方向とセル間の間隔を保持します。

Qt クイックレイアウトQML タイプを使用すると、レイアウトにプッシュされるアイテムに追加プロパティを付けることができます。例えば、アイテムの高さ、幅、サイズの最小値、最大値、優先値を指定することができます。

レイアウトは、ウィンドウや画面のサイズが変更されたときにUIが適切に拡大縮小され、常に利用可能な最大限のスペースを使用することを保証します。

GridLayout タイプの具体的な使用例としては、画面の向きに応じて行または列として使用することです。

以下のコード・スニペットでは、flow プロパティを使用して、画面の幅が画面の高さより大きい場合は左から右へ(行として)、そうでない場合は上から下へ(列として)グリッドの流れを設定しています:

ApplicationWindow {
    id: root
    visible: true
    width: 480
    height: 620

    GridLayout {
        anchors.fill: parent
        anchors.margins: 20
        rowSpacing: 20
        columnSpacing: 20
        flow:  width > height ? GridLayout.LeftToRight : GridLayout.TopToBottom
        Rectangle {
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "#5d5b59"
            Label {
                anchors.centerIn: parent
                text: "Top or left"
                color: "white"
            }
        }
        Rectangle {
            Layout.fillWidth: true
            Layout.fillHeight: true
            color: "#1e1b18"
            Label {
                anchors.centerIn: parent
                text: "Bottom or right"
                color: "white"
            }
        }
    }
}

画面のサイズを常に変更し、再計算することは、パフォーマンス・コストを伴います。モバイル機器や組み込み機器では、たとえばアニメーションオブジェクトのサイズや位置をフレームごとに再計算するのに必要なパワーがないかもしれません。レイアウトを使用する際にパフォーマンスの問題に直面した場合は、代わりにバインディングなどの他の方法を使用することを検討してください。

以下は、レイアウトでやってはいけないことです:

  • レイアウトの目的に反し、バインディングループの原因にもなります。
  • 定期的に評価される複雑なJavaScript関数を定義しないでください。これは、特にアニメーションの遷移中にパフォーマンスが低下する原因になります。
  • コンテナのサイズや子アイテムのサイズを決めつけない。利用可能なスペースの変化を吸収できる柔軟なレイアウト定義を心がけましょう。
  • デザインをピクセル単位で完璧にしたい場合は、レイアウトを使用しないでください。コンテンツアイテムは、利用可能なスペースに応じて自動的にサイズと位置が変更されます。

バインディングの使用

Qt Quick Layouts がニーズに合わない場合は、プロパティ・バインディングを使うことができます。バインディングは、他のオブジェクトの属性の変更や外部イベントの発生に応じて、オブジェクトが自動的にプロパティを更新することを可能にします。

オブジェクトのプロパティに値を割り当てる場合、静的な値を割り当てることも、JavaScriptの式にバインドすることもできます。前者の場合、プロパティに新しい値が代入されない限り、プロパティの値は変わりません。後者の場合、プロパティバインディングが作成され、評価された式の値が変更されるたびに、QMLエンジンによってプロパティの値が自動的に更新されます。

このタイプのポジショニングは最もダイナミックなものです。しかし、JavaScriptの式を常に評価することは、パフォーマンス上のコストを伴います。

Android、macOS、iOSのような)自動サポートがないプラットフォームでは、バインディングを使って低ピクセル密度や高ピクセル密度を扱うことができます。次のコード・スニペットは、Screen.pixelDensity 添付プロパティを使用して、ピクセル密度が低い、高い、または通常の画面で表示する異なる画像を指定します:

Image {
    source: {
        if (Screen.pixelDensity < 40)
        "image_low_dpi.png"
        else if (Screen.pixelDensity > 300)
        "image_high_dpi.png"
        else
        "image.png"
        }
    }

Android、macOS、iOSでは、アイコンや画像に対応する識別子(@2x@3x@4xなど)を使用して、解像度の高い代替リソースを提供し、リソースファイルに配置することができます。スクリーンのピクセル密度に合ったバージョンが自動的に選択されて使用されます。

例えば、以下のコード・スニペットは、Retinaディスプレイでartwork@2x.png:

Image {
    source: "artwork.png"
}

ピクセル密度の処理

ImageBorderImageText のようないくつかのQMLタイプは、指定されたプロパティに従って自動的に拡大縮小されます。もしImageの幅と高さが指定されていなければ、自動的にsource プロパティで指定されたソース画像のサイズが使われます。デフォルトでは、幅と高さを指定すると、イメージはそのサイズに拡大縮小されます。この動作は、fillMode プロパティを設定することで変更でき、代わりに画像を引き伸ばしてタイル状にすることができます。しかし、元の画像サイズは、高DPIディスプレイでは小さすぎるように見えるかもしれません。

BorderImage は、各画像の一部を拡大縮小したりタイル状に並べたりして、画像から境界線を作成するために使われます。これは、ソース画像を9つの領域に分割し、プロパティ値に従って拡大縮小またはタイル化します。しかし、角はまったく拡大縮小されないため、高DPIディスプレイでは最適な結果が得られないことがあります。

Text QMLタイプは、明示的に設定されない限り、必要な領域数を判断し、それに応じてwidthheight プロパティを設定しようとします。fontPointSize プロパティはデバイスに依存しない方法でポイントサイズを設定します。しかし、フォントをポイントで指定し、その他のサイズをピクセルで指定すると、ポイントがディスプレイの密度に依存しないため、問題が発生します。低DPIディスプレイでは正しく見える文字列を囲むフレームも、高DPIディスプレイでは小さすぎてテキストが切れてしまう可能性が高い。

高 DPI サポートのレベルと、サポートされるプラットフォームが使用する技法は、プラットフォームによって異なります。以下のセクションでは、高DPIディスプレイで画面コンテンツを拡大縮小するためのさまざまなアプローチについて説明します。

Qt の高 DPI サポートとサポートされているプラットフォームの詳細については、高 DPI を参照してください。

macOS と iOS での高 DPI スケーリング

macOS と iOS では、アプリケーションは従来の DPI スケーリングに代わる高 DPI スケーリングを使用します。従来の方法では、アプリケーションには、フォントサイズやレイアウトなどの倍率に使用されるDPI値が表示されます。新しいアプローチでは、オペレーティングシステムがQtにスケーリング比率を提供し、それを使用してグラフィックス出力をスケーリングします。より大きなバッファを割り当て、スケーリング変換を設定します。

このアプローチの利点は、ベクターグラフィックスやフォントが自動的に拡大縮小され、既存のアプリケーションが変更されずに動作する傾向があることです。しかし、ラスターコンテンツの場合は、高解像度の代替リソースが必要です。

スケーリングは、QtQuick と QtWidgets スタックに実装されているほか、QtGui と Cocoa プラットフォーム・プラグインでも一般的にサポートされています。

OSはウィンドウ、イベント、デスクトップのジオメトリをスケーリングします。Cocoaプラットフォーム・プラグインは、QWindow::devicePixelRatio ()またはQScreen::devicePixelRatio ()として、またバッキングストア上でスケーリング比率を設定します。

QtWidgets では、QPainter がバッキングストアからdevicePixelRatio() を受け取り、スケーリング比率として解釈します。

しかし、OpenGLではピクセルは常にデバイスピクセルです。例えば、glViewport()に渡されたジオメトリは、devicePixelRatio()によってスケーリングされる必要があります。

指定されたフォントサイズ(ポイントまたはピクセル)は変更されず、文字列はUIの他の部分と比較して相対的なサイズを保持します。フ ォ ン ト は描画の一部 と し て拡大縮小 さ れますので、 サイズ 12 のフ ォ ン ト は、 それがポ イ ン ト 単位で指定 さ れてい る か ピ ク セル単位で指定 さ れてい る かにかかわ ら ず、 実質的には 2 倍の拡大縮小でサ イ ズ 24 のフ ォ ン ト にな り ます。px単位はデバイスに依存しないピクセルとして解釈され、高DPIディスプレイでフォントが小さく表示されないようにします。

倍率の計算

参照デバイスとして高DPIデバイスを1つ選択し、画像とフォントのサイズと余白を実際の画面サイズに調整するためのスケーリング比を計算することができます。

次のコード・スニペットは、Nexus 5 Android デバイスの DPI、高さ、幅の参照値、QRect クラスが返す実際の画面サイズ、qApp グローバル・ポインタが返す画面の論理 DPI 値を使用して、画像サイズと余白 (m_ratio) のスケーリング比と、フォント・サイズ (m_ratioFont) のスケーリング比を計算します:

qreal refDpi = 216.;
qreal refHeight = 1776.;
qreal refWidth = 1080.;
QRect rect = QGuiApplication::primaryScreen()->geometry();
qreal height = qMax(rect.width(), rect.height());
qreal width = qMin(rect.width(), rect.height());
qreal dpi = QGuiApplication::primaryScreen()->logicalDotsPerInch();
m_ratio = qMin(height/refHeight, width/refWidth);
m_ratioFont = qMin(height*refDpi/(dpi*refHeight), width*refDpi/(dpi*refWidth));

妥当な拡大縮小率を得るには、参照デバイスのデフォルトの向き(この場合は縦向き)に従って高さと幅の値を設定する必要があります。

下記の コ ー ド では、 フ ォ ン ト の拡大縮小比が 1 よ り も 小 さ く な り 、 フ ォ ン ト サ イ ズが小 さ く な り す ぎ る と き は1 に設定 し てい ます:

int tempTimeColumnWidth = 600;
int tempTrackHeaderWidth = 270;
if (m_ratioFont < 1.) {
    m_ratioFont = 1;

追加計算が必要なエッジケースを見つけるために、ターゲットデバイスで実験する必要があります。スクリーンによっては、短すぎたり狭すぎたりして、予定していたコンテンツがすべて収まらず、独自のレイアウトが必要になる場合があります。たとえば、アスペクト比が1:1のような非定型の画面では、一部のコンテンツを隠したり置き換えたりする必要があるかもしれません。

QQmlPropertyMap 、すべてのサイズに拡大縮小率を適用して、画像やフォント、余白を拡大縮小することができます:

m_sizes = new QQmlPropertyMap(this);
m_sizes->insert(QLatin1String("trackHeaderHeight"), QVariant(applyRatio(270)));
m_sizes->insert(QLatin1String("trackHeaderWidth"), QVariant(applyRatio(tempTrackHeaderWidth)));
m_sizes->insert(QLatin1String("timeColumnWidth"), QVariant(applyRatio(tempTimeColumnWidth)));
m_sizes->insert(QLatin1String("conferenceHeaderHeight"), QVariant(applyRatio(158)));
m_sizes->insert(QLatin1String("dayWidth"), QVariant(applyRatio(150)));
m_sizes->insert(QLatin1String("favoriteImageHeight"), QVariant(applyRatio(76)));
m_sizes->insert(QLatin1String("favoriteImageWidth"), QVariant(applyRatio(80)));
m_sizes->insert(QLatin1String("titleHeight"), QVariant(applyRatio(60)));
m_sizes->insert(QLatin1String("backHeight"), QVariant(applyRatio(74)));
m_sizes->insert(QLatin1String("backWidth"), QVariant(applyRatio(42)));
m_sizes->insert(QLatin1String("logoHeight"), QVariant(applyRatio(100)));
m_sizes->insert(QLatin1String("logoWidth"), QVariant(applyRatio(286)));

m_fonts = new QQmlPropertyMap(this);
m_fonts->insert(QLatin1String("six_pt"), QVariant(applyFontRatio(9)));
m_fonts->insert(QLatin1String("seven_pt"), QVariant(applyFontRatio(10)));
m_fonts->insert(QLatin1String("eight_pt"), QVariant(applyFontRatio(12)));
m_fonts->insert(QLatin1String("ten_pt"), QVariant(applyFontRatio(14)));
m_fonts->insert(QLatin1String("twelve_pt"), QVariant(applyFontRatio(16)));

m_margins = new QQmlPropertyMap(this);
m_margins->insert(QLatin1String("five"), QVariant(applyRatio(5)));
m_margins->insert(QLatin1String("seven"), QVariant(applyRatio(7)));
m_margins->insert(QLatin1String("ten"), QVariant(applyRatio(10)));
m_margins->insert(QLatin1String("fifteen"), QVariant(applyRatio(15)));
m_margins->insert(QLatin1String("twenty"), QVariant(applyRatio(20)));
m_margins->insert(QLatin1String("thirty"), QVariant(applyRatio(30)));

画像 ・ フ ォ ン ト ・ 余白を拡縮す る : 下記の コ ー ド ス ニ ッペ ッ ト の関数は、 拡縮率を フ ォ ン ト ・ 画像 ・ 余白に適用 し ます:

int Theme::applyFontRatio(const int value)
{
    return int(value * m_ratioFont);
}

int Theme::applyRatio(const int value)
{
    return qMax(2, int(value * m_ratio));
}

このテクニックは、ターゲット・デバイスのスクリーン・サイズがあまり違わない場合に、妥当な結果をもたらします。違いが大きい場合は、基準値を変えて複数のレイアウトを作成することを検討してください。

プラットフォームによるファイルの読み込み

QQmlFileSelector 、QMLファイルの読み込みにQFileSelector 。これにより、アプリケーションを実行するプラットフォームに応じて、別のリソースをロードすることができます。例えば、+android ファイルセレクタを使用することで、Android端末で実行する際に異なる画像ファイルを読み込むことができます。

ファイル・セレクタとシングルトン・オブジェクトを併用すると、特定のプラットフォームでオブジェクトの単一インスタンスにアクセスできます。

ファイル・セレクタは静的で、プラットフォーム固有のファイルがプラットフォームにちなんだ名前のサブフォルダに格納されるファイル構造を強制します。UIの一部をオンデマンドでロードするために、より動的なソリューションが必要な場合は、ローダーを使うことができます。

ターゲットとなるプラットフォームは、さまざまな方法で、異なるディスプレイ密度用の代替リソースのロードを自動化するかもしれない。AndroidやiOSでは、画像の高DPIバージョンを示すために@2xというファイル名の接尾辞が使われます。ImageQMLタイプやQIcon クラスは、@2xバージョンの画像やアイコンが提供されていれば自動的に読み込みます。QImageQPixmap クラスは、@2xバージョンの画像のdevicePixelRatio を自動的に2 に設定しますが、実際に@2xバージョンを使うにはコードを追加する必要があります:

if ( QGuiApplication::primaryScreen()->devicePixelRatio() >= 2 ) {
    imageVariant = "@2x";
} else {
    imageVariant = "";
}

Androidは、代替リソースを作成できる一般的な画面サイズ(small、normal、large、xlarge)と濃度(ldpi、mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi)を定義しています。Androidは実行時に現在のデバイス構成を検出し、アプリケーションに適切なリソースをロードします。しかし、Android 3.2(APIレベル13)から、これらのサイズグループは廃止され、利用可能な画面幅に基づいて画面サイズを管理する新しい手法が採用されました。

コンポーネントの読み込み

Loader は、QML ファイル(source プロパティを使用)または Component オブジェクト(sourceComponent プロパティを使用)をロードすることができます。これは、コンポーネントが必要になるまで、その作成を遅らせるのに便利です。例えば、コンポーネントをオンデマンドで作成する場合や、パフォーマンス上の理由からコンポーネントを不必要に作成しない場合などです。

また、あるプラットフォームがある機能をサポートしていないために、UIの一部が特定のプラットフォームでは必要ないという状況に対応するために、ローダーを使用することもできます。アプリケーションが動作しているデバイスで不要なビューを表示する代わりに、そのビューが非表示になっていると判断し、ローダーを使ってその代わりに別のものを表示することができます。

向きの切り替え

Screen.orientation attached プロパティには、加速度センサー(利用可能な場合)による画面の現在の向きが格納されます。デスクトップ・コンピュータでは、この値は通常変化しません。

primaryOrientationorientation に続く場合、デバイスの持ち方によって、表示されるすべてのコンテンツが自動的に回転することを意味します。primaryOrientation が変更されないにもかかわらず、方向が変更される場合、デバイスは自身のディスプレイを回転させない可能性があります。その場合、Item.rotation またはItem.transform を使ってコンテンツを回転させる必要があるかもしれません。

アプリケーションのトップレベルページ定義と再利用可能なコンポーネント定義では、レイアウト構造に1つのQMLレイアウト定義を使用する必要があります。この1つの定義には、デバイスの向きやアスペクト比に応じたレイアウトデザインを含める必要があります。その理由は、向きが切り替わる際のパフォーマンスが重要であるためです。そのため、向きが切り替わる際に、両方の向きに必要なコンポーネントがすべて読み込まれるようにするのがよいでしょう。

逆に、Loader を使用して、別々のオリエンテーションで必要となる追加の QML をロードする場合は、オリエンテーション変更のパフォーマンスに影響するため、徹底的なテストを行う必要があります。

オリエンテーション間のレイアウトアニメーションを有効にするためには、アンカー定義は同じ内包コンポーネント内に存在しなければなりません。したがって、ページやコンポーネントの構造は、子コンポーネントの共通セット、アンカー定義の共通セット、コンポーネントがサポートするさまざまなアスペクト比を表すステートのコレクション(StateGroup で定義)で構成される必要があります。

ページ内に含まれるコンポーネントが、多数の異なるフォームファクタ定義でホストされる必要がある場合、ビューのレイアウト状態は、ページ(その直接のコンテナ)のアスペクト比に依存する必要があります。同様に、コンポーネントの異なるインスタンスは、UI内の多数の異なるコンテナ内に配置されるかもしれないので、そのレイアウト状態は、その親のアスペクト比によって決定されるべきである。結論として、レイアウト状態は常に、直接のコンテナの縦横比(現在のデバイス画面の「向き」ではない)に従うべきである。

各レイアウトState 内では、ネイティブのQMLレイアウト定義を使用して、アイテム間の関係を定義する必要があります。詳細は以下を参照してください。アンカーレイアウトの場合、(トップレベルの方向転換をトリガーとした)状態遷移の間、AnchorAnimation 要素を使用して遷移を制御することができます。場合によっては、アイテムの幅などにNumberAnimation 。アニメーションの各フレームでは、複雑なJavaScriptの計算を避けることを忘れないでください。単純なアンカー定義とアンカーアニメーションを使用することで、ほとんどの場合、この問題を解決することができます。

さらに考慮すべきケースがいくつかあります:

  • 1つのページが、横向きと縦向きでまったく異なる、つまり子アイテムがすべて異なる場合はどうでしょう?各ページについて、別々のレイアウト定義を持つ2つの子コンポーネントを用意し、各状態でどちらか一方のアイテムの不透明度をゼロにします。不透明度にNumberAnimation の遷移を適用するだけで、クロスフェード・アニメーションを使うことができます。
  • 同じレイアウトコンテンツを縦と横で30%以上共有する単一ページがある場合はどうでしょう?その場合、横向きと縦向きの状態を持つ1つのコンポーネントと、不透明度(または位置)が向きの状態に依存する個別の子アイテムのコレクションを持つことを検討してください。こうすることで、レイアウトアニメーションを方向間で共有するアイテムに使用することができ、他のアイテムはフェードイン/フェードアウト、または画面のオン/オフでアニメーションさせることができます。
  • ハンドヘルドデバイスで2つのページを同時に表示する必要がある場合、例えばフォームファクタの大きなデバイスではどうでしょうか?この場合、ビュー・コンポーネントはもはや全画面を占有しないことに注意してください。したがって、すべてのコンポーネント(特に、リスト・デリゲート・アイテム)において、画面の幅ではなく、含むコンポーネントの幅のサイズに依存することを覚えておくことが重要です。この場合、Component.onCompleted()ハンドラで幅を設定し、値が設定される前にリスト項目のデリゲートが構築されていることを確認する必要があるかもしれません。
  • 2つのオリエンテーションを一度にメモリに入れるには、メモリを消費しすぎる場合はどうすればよいですか?一度に両方のバージョンのビューをメモリに保持できない場合は、必要に応じてLoader 。ただし、レイアウト切り替え時のクロスフェードアニメーションのパフォーマンスには注意してください。1つの解決策は、ページの子である2つの "スプラッシュスクリーン "アイテムを持ち、回転中にそれらの間でクロスフェードさせることです。その後、Loader を使用して、実際のモデルデータを別の子アイテムにロードする別の子コンポーネントをロードし、Loader が完了したら、その子アイテムにクロスフェードします。

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