本页内容

咖啡机

一款采用Qt Quick 技术、具备基于状态的自定义用户界面的应用程序。

咖啡机界面显示“开始使用”按钮

该应用演示了如何以跨平台、支持多种屏幕尺寸且响应式的方式,实现典型的产品订购用户界面。

运行示例

您可以通过以下方式运行示例:

UI 操作指南

本节将引导您了解该应用程序的典型用户流程。

选择配方

可选咖啡种类一览

咖啡机应用程序允许您选择咖啡种类,并显示该种类剩余可订购的咖啡数量。

咖啡定制

用于自定义咖啡混合比例的滑块

选择配方后,应用将显示该咖啡混合配方中各成分的比例:

  • 现煮咖啡
  • 热牛奶
  • 奶泡
  • 糖

用户可通过滑块调整这些比例。

显示冲泡状态

提示用户放入杯子

一旦用户确认杯子已放入机器,冲泡过程便会开始。

冲泡开始后,应用程序会显示冲泡过程的动画。

咖啡已冲泡完成

冲泡过程结束后,应用程序会显示盛有所需咖啡混合饮品的咖啡杯几秒钟,然后返回起始页面。

工作原理

下面我们将讨论这些功能的实现方式。

适应屏幕尺寸和方向

应用程序窗口的根对象具有高度和宽度的初始值,这些值将在桌面平台上用作窗口大小。默认的QWindow::AutomaticVisibility 可确保在需要该功能的平台(如移动平台)上,窗口以最大化或全屏模式显示。

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

    background: Rectangle {
        color: Colors.currentTheme.background
    }

在此基础上,ApplicationWindow 的子对象会获取ApplicationWindow 的尺寸,并据此确定自身尺寸。

该应用在所有应用页面组件中均使用 `GridLayout `,以便轻松适应屏幕方向的变化。

Android 版咖啡机选择页面的横向显示模式

{当 Android 设备处于横屏模式时,屏幕将切换为横屏}

Windows 版咖啡机选择页面的横向布局

{横屏模式是 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 实现的。

实现起始页面

应用程序启动时,会将Home 页面作为StackView 中的初始项展示给用户:

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 中将choosingCoffee 组件推至Home 组件之上。

实现咖啡选择功能

在“咖啡选择”页面上显示ChoosingCoffee.qml ,用户在此可以看到 4 种不同的咖啡选项可供选择。这些选项以CoffeeCards 的形式显示,位于ChoosingCoffee.qml 中的GridLayout 内部:

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 页面中滑块的数值会存储在CoffeeConfig 中,以便后续通过Synchronizer QML类型进行调用。

Synchronizer {
     sourceObject: settingsForm.coffeeConfig
     sourceProperty: "sugarAmount"
     targetObject: settingsForm.sugarSlider
     targetProperty: "value"
}

点击“开始”按钮会将ApplicationFlow.qml 的状态更改为“插入”,应用程序将显示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()
    }
}
实现“咖啡已好”功能

“准备就绪”页面会显示一个装有用户所选配置的咖啡杯,并配有“您的咖啡已准备就绪”的文字和一个勾号图标。

当此页面显示时,Timer 开始运行,一旦达到设定的间隔时间,用户将被重定向回Home.qml 。

源文件

Squish GUI 测试

该应用程序附带了针对 Qt for Android 的Squish GUI 测试。这些测试使用Squish for Qt制作,采用 Python 编写,位于应用程序的 test 目录下。

在使用 Squish for Qt for Android 时,请确保使用Qt 内置钩子,并通过 adb转发 Squish 端口。如果dlopen 失败并出现“无法加载库”的错误,请在 CMake 配置中禁用QT_USE_TARGET_ANDROID_BUILD_DIR ,或从Qt Creator 中的Projects->Build Settings->CMake->Current Configuration 中将其清除。

如果您没有 Squish 许可证,可以申请免费试用。

示例项目 @ code.qt.io

另请参阅 所有 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.