コーヒーマシン
状態管理型のカスタムユーザーインターフェースを備えたQt Quick アプリケーション。

このアプリは、製品の注文を行うための典型的なユーザーインターフェースを、クロスプラットフォームかつ複数の画面サイズに対応し、レスポンシブな方法で実装する方法を示しています。
例の動作
サンプルは次の手順で実行できます。
- Qt Creator
Welcome モードを開き、Examples からこのサンプルを選択してください。詳細については、Qt Creator の「チュートリアル:ビルドと実行」を参照してください。
- Qt Extension for Visual Studio Code
Command Palette から `Qt: Open Qt examples ` コマンドを実行し、リストからこのサンプルを選択します。詳細については、Qt Extension for Visual Studio Code の「チュートリアル:ビルドと実行」を参照してください。
UI の概要
このセクションでは、アプリケーションの一般的なユーザーフローについて解説します。
レシピの選択

コーヒーマシンアプリケーションでは、コーヒーの種類を選択でき、その種類のコーヒーがあと何杯注文できるかが表示されます。
コーヒーのカスタマイズ

レシピを選択すると、アプリにはそのコーヒーブレンドに含まれる以下の比率が表示されます:
- 淹れたてのコーヒー
- 温めたミルク
- ミルクフォーム
- 砂糖
これらはスライダーを使って調整できます。
抽出状況の表示

ユーザーがカップがマシンに入っていることを確認すると、抽出が開始されます。
抽出が開始されると、アプリには抽出プロセスのアニメーションが表示されます。
コーヒーが完成しました
抽出プロセスが終了すると、アプリには希望のコーヒーミックスが入ったコーヒーカップが数秒間表示された後、スタートページに戻ります。
仕組み
ここでは、これらの機能がどのように実装されているかについて説明します。
画面サイズと向きへの適応
アプリケーションウィンドウのルートオブジェクトには、高さおよび幅の初期値が設定されており、これらはデスクトッププラットフォームでのウィンドウサイズとして使用されます。デフォルトのQWindow::AutomaticVisibility は、モバイルプラットフォームなど、必要とされるプラットフォームにおいて、ウィンドウが最大化または全画面表示されるようにします。
ApplicationWindow {
visible: true
width: 1000
height: 600
title: qsTr("Coffee")
background: Rectangle {
color: Colors.currentTheme.background
}そこから、ApplicationWindow の子オブジェクトはApplicationWindow のサイズを取得し、それに応じて自身のサイズを決定します。
このアプリでは、画面の向きが変わっても容易に対応できるよう、アプリケーションのページコンポーネント全体でGridLayout を使用しています。

{Androidデバイスの向きが横向きになると、画面も横向きに切り替わります}

{Windowsデスクトップでは、横向きモードがデフォルトの向きです}
注: デスクトップ版では 、幅が高さよりも大きくなければなりません。
アプリページ間の移動
このアプリケーションでは、StackView QMLタイプを使用して、アプリのさまざまなページを表示しています。各ページコンポーネントを処理するStackView は、ApplicationFlowForm.ui.qml に実装されています。
あるページから次のページへ移動すると、ApplicationFlow.qml の状態が変更され、必要なプロパティの変更はPropertyChanges QML タイプによって処理されます:
states: [
State {
name: "Home"
PropertyChanges {
target: toolbar
backButton.opacity: 0
backButton.enabled: false
themeButton.opacity: 0
themeButton.enabled: false
logo.sourceSize.width: 70
logo.sourceSize.height: 50
}これらの状態変化の際に発生するアニメーションは、ApplicationFLowForm.ui.qml 内のStackView コンポーネント内で、Transition およびPropertyAnimation を使用して実装されています。
スタートページの実装
アプリケーションは、StackView の最初のアイテムとして、ユーザーにHome ページを表示することから開始します:
StackView {
id: stack
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: parent.height / 20
pushEnter: Transition {
PropertyAnimation {
property: "x"
from: stack.width
to: 0
duration: 400
}
}Home コンポーネントの構造は、Item コンポーネントをルートオブジェクトとして配置し、ステートマシンと適切なプロパティエイリアスを設定した上で、GridLayout を配置することで構成されています。この同じ構造は、アプリ内のすべてのページコンポーネントで使用されます。
Home ページには、上部にQtロゴが入ったコーヒーカップの画像、タイトルとして「Coffee Machine」、ユーザーが期待できる内容に関するキャッチーな説明文、そして「getStartedButton 」ボタンが表示されます。
ユーザーは「getStartedButton 」ボタンを押すことで先に進むことができ、「onClicked 」ボタンの機能はApplicationFlow.qml で実装されています:
getStartedbutton.onClicked: {
applicationFlow.state = "Coffee-selection"
applicationFlow.stack.pushItem(applicationFlow.choosingCoffee, {appFlow: applicationFlow})
}これにより、ApplicationFlow.qml 内で状態が「Coffee-selection」に変更され、StackView 内のHome コンポーネントの上にchoosingCoffee コンポーネントがプッシュされます。
コーヒーの選択機能の実装
「コーヒーの選択」ページ(ChoosingCoffee.qml )には、ユーザーが選択できる4つの異なるコーヒーのオプションが表示されます。これらのオプションは、ChoosingCoffee.qml 内のGridLayout 内に配置されたCoffeeCards として表示されます:
GridLayout {
id: cards
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
rowSpacing: 20
columnSpacing: 20
CoffeeCard {
id: cappuccino
coffeeName: "Cappuccino"
ingredients: "Milk, Espresso, Foam"
time: 2
}
CoffeeCard {
id: latte
coffeeName: "Latte"
ingredients: "Coffee, Foam"
time: 3
}
CoffeeCard {
id: espresso
coffeeName: "Espresso"
ingredients: "Milk, Espresso"
time: 2
}
CoffeeCard {
id: macchiato
coffeeName: "Macchiato"
ingredients: "Milk foam, Espresso"
time: 4
}
}CoffeeCard の実装は、CoffeeCard.qml にあります。
これらのカードは、ApplicationWindow のルートオブジェクトが従い、ステートマシンを介してChoosingCoffee.qml およびその中のGridLayout に継承される、利用可能な画面の幅と高さのプロパティに応じて、グリッド形式または行形式のいずれかで表示されます。
CoffeeCards 各カードは、名称、抽出時間、材料、および現在利用可能なカップ数が異なります。
このページでは、ユーザーは画面右上隅にある小さな太陽のようなアイコンボタンを押すことで、初めてアプリケーションのテーマを変更することもできます。テーマボタンを押すと、ApplicationFlow.qml 内のthemeButton 関数が呼び出されます:
function themeButton() {
if (Colors.currentTheme == Colors.dark) {
Colors.currentTheme = Colors.light
} else {
Colors.currentTheme = Colors.dark
}
}この関数は、Colors.qml のcurrentTheme プロパティを変更し、プロパティバインディングによってアプリ全体の色が自動的に変更されます。アプリで使用されるすべての色は、Colors.qml に定義されています。
テーマがライトテーマに切り替わると、テーマ変更アイコンが半月を表現するアイコンに変わります。
コーヒーカードのいずれかをタップすると、CoffeeCard.qml 内のAbstractButton で状態が変更され、Transition を通じてNumberAnimation がトリガーされます:
AbstractButton {
width: parent.width - 2
height: parent.height - 2
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
id: button
hoverEnabled: true
checkable: true
enabled: (root.cupsLeft != 0) ? true : false
transitions: Transition {
NumberAnimation {
properties: "scale"
duration: 50
easing.type: Easing.InOutQuad
}
}これにより、選択されたコーヒーカードが縮小され、カードの縁が緑色に変わり、ユーザーに「コーヒーが実際に選択された」という表現が与えられます。
各コーヒーカードのbutton プロパティのエイリアスであるonClicked 関数は、ApplicationFlow.qml にある関数にバインドされています。ユーザーがいずれかのコーヒーカードをタップすると、選択されたコーヒーオプションに対応する名前の関数が呼び出されます。この関数は、ApplicationFlow.qml の状態をSettings に設定し、新しいコンポーネントをStackView にプッシュし、それに応じて材料のプロパティを設定します。
コーヒー設定の実装
このページでは、ユーザーはカスタムSlider QMLタイプを調整することで、好みに合わせてコーヒーのオプションをカスタマイズできます。スライダーの値を変更すると、コーヒーカップ内の液面レベルが変化します。これは、Cup.qml 内の液体画像の高さを、対応するスライダーの値にバインドすることで実現されています。
Settings ページのスライダーの値は、Synchronizer というQMLタイプを使用して、後で利用できるようCoffeeConfig に保存されます。
Synchronizer {
sourceObject: settingsForm.coffeeConfig
sourceProperty: "sugarAmount"
targetObject: settingsForm.sugarSlider
targetProperty: "value"
}「Start」ボタンをクリックすると、ApplicationFlow.qml の状態が「Insert」に変更され、アプリはInsert.qml を表示します。
カップの挿入機能の実装
このページでは、抽出プロセスを開始する前に、ユーザーにカップをマシンにセットするよう指示されます。
Continue ボタンを押すと、アプリはProgress ページに移動します。
コーヒーの抽出機能の実装
進行状況ページには、コーヒーカップと進行状況バーが表示され、それぞれ独自の方法で抽出プロセスをリアルタイムに示します。
ここで、コーヒーカップがいっぱいになると、Settings ページでユーザーが選択した設定とまったく同じ状態が表示されます。これは、Cup のプロパティ変数を、ApplicationFlow.qml に保存された対応する値にバインドすることで実現されています。
コーヒーカップにコーヒーを注ぐアニメーションは、状態エンジンTransition およびSmoothedAnimation によって実行されます。
Cup {
id: cup
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
state: "0"
}プログレスバーのアニメーションは、Behavior を使用して実装されています。
Behavior on greenBar.width {
SmoothedAnimation {
easing.type: Easing.Linear
velocity: (progressForm.contentItem.width / progressForm.brewTime) * 1000
}
}Timer は、抽出が完了したらアプリケーションの状態を更新します。
Timer {
id: timer
interval: progressForm.brewTime
running: true
onTriggered: {
progressForm.appFlow.onFinished()
}
}「コーヒーができました」ページの実装
「Ready」ページには、ユーザーが選択した設定に従って満たされたコーヒーカップと、「Your coffee is ready」というテキスト、およびチェックアイコンが表示されます。
このページが表示されると、Timer が実行され、設定された間隔に達すると、ユーザーはHome.qml に戻されます。
ソースファイル
Squish GUI テスト
このアプリケーションには、Qt for Android 向けのSquish GUI テストが付属しています。これらのテストはSquish for Qtを使用して Python で記述されており、アプリケーションの test ディレクトリ内にあります。
Squish for Qt for Android を使用する場合は、Qt の組み込みフックを使用し、adb を使用してSquish ポートをフォワードするようにしてください。dlopen が失敗し、「Cannot load library」というエラーが表示される場合は、CMake 設定からQT_USE_TARGET_ANDROID_BUILD_DIR を無効にするか、Qt Creator 内のProjects->Build Settings->CMake->Current Configuration からこれを削除してください。
Squishのライセンスをお持ちでない場合は、無料トライアルをご利用いただけます。
「すべての 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.