コーヒーマシン

Qt Quick ステートベースのカスタムユーザインタフェースを持つアプリケーション。

コーヒーマシン サンプル概要

このアプリは、クロスプラットフォーム、マルチスクリーンサイズ、レスポンシブで、商品注文のための典型的なユーザーインターフェースを実装する方法を示しています。

レシピの選択

コーヒーの選択

コーヒーマシーンアプリでは、コーヒーの種類を選択することができ、その種類のコーヒーの注文残数が表示されます。

コーヒーのカスタマイズ

レシピを選択すると、ブレンドコーヒーの比率が表示されます:

  • 抽出コーヒー
  • ホットミルク
  • ミルクフォーム
  • 砂糖

スライダーで変更できます。

抽出ステータスの表示

ユーザーがカップがマシンに入ったことを確認すると、抽出が開始されます。

抽出が開始されると、アプリは抽出プロセスをアニメーションで表示します。

コーヒーの準備ができました

抽出プロセスが終了すると、アプリは数秒間、希望のコーヒーミックスが入ったコーヒーカップを表示し、その後スタートページに戻ります。

どのように機能するか

ここでは、これらの機能がどのように実装されているかについて説明します。

画面サイズと向きへの対応

アプリケーションのウィンドウ・ルート・オブジェクトには、高さと幅の初期値があり、デスクトップ・プラットフォームでのウィンドウ・サイズとして使用されます。デフォルトのQWindow::AutomaticVisibility は、モバイル・プラットフォームなど、最大化またはフルスクリーンを必要とするプラットフォームで、ウィンドウが最大化またはフルスクリーンとして表示されることを保証します。

ApplicationWindow {
    visible: true
    width: 1000
    height: 600
    title: qsTr("Coffee")

そこから、ApplicationWindow の子オブジェクトは、ApplicationWindow のサイズを取得し、それに応じて自身のサイズを決定します。

このアプリでは、画面の向きが変わっても簡単に適応できるように、アプリケーションページのコンポーネント全体でGridLayout を使用しています。

このアプリでは、StackView QMLタイプを使用して、アプリのさまざまなページを表示しています。異なるページコンポーネントを扱うStackViewApplicationFlowForm.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.qmlStackView コンポーネント内のTransitionPropertyAnimation で実装されています。

スタートページの実装

アプリケーションは、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
    initialItem: Home {
        id: home
        visible: true
        state: applicationFlow.mode
    }
    pushEnter: Transition {
        PropertyAnimation {
            property: "x"
            from: stack.width
            to: 0
            duration: 400
        }
    }

Home コンポーネントは、ステートマシンと適切なプロパティのエイリアスを持つルートオブジェクトとしてItem コンポーネントを配置し、その後にGridLayout を配置することで構造化されています。これと同じ種類の構造化が、すべてのアプリ・ページ・コンポーネントで使用されます。

Home ページには、Qt のロゴが入ったコーヒーカップの画像が表示され、Coffee Machine というタイトル、キャプション、getStartedButton ボタンが表示されます。

ユーザは、getStartedButton を押すことで前に進むことができます。ボタンonClicked の機能は、ApplicationFlow.qml に実装されています:

home.getStartedbutton.onClicked: {
    applicationFlow.state = "Coffee-selection"
    stack.push(choosingCoffee)
}

これにより、ApplicationFlow.qml の状態が "Coffee-selection "に変化し、choosingCoffee コンポーネントがHome コンポーネントStackView の上に押し出される。

コーヒーセレクションの実装

コーヒー選択ページChoosingCoffee.qml が表示され、ユーザーは4つの異なるコーヒーの選択肢から選ぶことができます。これらのオプションはCoffeeCards として表示され、ChoosingCoffee.qmlGridLayout の中にあります:

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
        cupsLeft: applicationFlow.cappuccinos
    }
    CoffeeCard {
        id: latte
        coffeeName: "Latte"
        ingredients: "Coffee, Foam"
        time: 3
        cupsLeft: applicationFlow.lattes
    }
    CoffeeCard {
        id: espresso
        coffeeName: "Espresso"
        ingredients: "Milk, Espresso"
        time: 2
        cupsLeft: applicationFlow.espressos
    }
    CoffeeCard {
        id: macchiato
        coffeeName: "Macchiato"
        ingredients: "Milk foam, Espresso"
        time: 4
        cupsLeft: applicationFlow.macchiatos
    }
}

CoffeeCard の実装はCoffeeCard.qml にあります。

これらのカードは、ApplicationWindow ルート・オブジェクトが従い、ステート・マシンを介して、ChoosingCoffee.qmlGridLayout に渡される、利用可能なスクリーン幅と高さのプロパティに応じて、グリッドまたは行のタイプのいずれかで表示されます。

CoffeeCards このページでは、名前、抽出時間、材料、現在利用可能なカップ数などを変更することができます。

このページでは、画面の右上にある小さな太陽のようなアイコンボタンを押すことで、ユーザーは初めてアプリケーションのテーマを変更することもできます。テーマボタンを押すと、ApplicationFlow.qmlthemeButton 関数が呼び出されます:

function themeButton() {
    if (Colors.currentTheme == Colors.dark) {
        Colors.currentTheme = Colors.light
    } else {
        Colors.currentTheme = Colors.dark
    }
}

この関数はColors.qmlcurrentTheme プロパティを変更し、プロパティバインディングによってアプリ全体の色が自動的に変更されます。アプリで使用される色はすべてColors.qml にあります。

テーマをライトテーマに切り替えると、テーマ変更ボタンのアイコンが半月に変わります。

コーヒーカードのどれかを押すと、CoffeeCard.qmlAbstractButton 内の状態変化がトリガーされ、NumberAnimation からTransition までがトリガーされます:

AbstractButton {
    width: parent.width - 2
    height: parent.height - 2
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.verticalCenter: parent.verticalCenter
    id: button
    hoverEnabled: true
    checkable: true
    enabled: (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 内部の液体イメージの高さを、対応するスライダーの値にバインドすることで可能になります。

スライダーの値はonValueChanged 関数を通してApplicationFLow.qml のプロパティ変数に格納されます。

coffeeSlider.onValueChanged: {
    applicationFlow.coffeeAmount = coffeeSlider.value
}

Startボタンをクリックすると、ApplicationFlow.qml の状態が "Insert "に変わり、アプリはInsert.qml を表示する。

挿入カップの実装

このページでユーザーは、抽出プロセスを開始する前に、カップをマシンに挿入するよう指示されます。

Continue ボタンを押すと、アプリはProgress ページに移動します。

コーヒーの抽出

このページでは、コーヒーカップとプログレスバーが表示され、それぞれの方法で抽出プロセスをリアルタイムで知らせます。

コーヒーカップが満たされると、Settings ページでユーザーが選択したものとまったく同じ構成が表示されます。これは、Cup プロパティ変数を、ApplicationFlow.qml で保存された対応する値にバインドすることで確実になっています。

コーヒー・カップを満たすアニメーションは、ステート・エンジンTransitionSmoothedAnimation を使用しています。

Cup {
    id: cup
    Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
    state: "0"
}

プログレスバーのアニメーションは、Behavior で実装されています。

Behavior on greenBar.width {
    SmoothedAnimation {
        easing.type: Easing.Linear
        velocity: (contentItem.width / brewTime) * 1000
    }
}

Timer は、抽出が完了するとアプリケーションの状態を更新します。

Timer {
    id: timer
    interval: brewTime
    running: true
    onTriggered: {
        applicationFlow.onFinished()
    }
}
コーヒーレディの実装

Readyページでは、ユーザーが選択した構成で満たされたコーヒーカップが、"Your coffee is ready "というテキストとチェックアイコンとともに表示されます。

このページが表示されると、Timer が実行され、設定された間隔に達すると、ユーザーはHome.qml に戻ります。

プロジェクト例 @ code.qt.io

© 2025 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.