커피 머신

상태 기반 사용자 지정 사용자 인터페이스를 갖춘 Qt Quick 애플리케이션입니다.

'시작하기' 버튼이 표시된 커피 머신 UI

이 앱은 제품 주문을 위한 일반적인 사용자 인터페이스를 구현하는 크로스 플랫폼, 다중 화면 크기 및 반응형 방식을 보여줍니다.

예제 실행하기

에서 예제를 실행하려면 Qt Creator에서 Welcome 모드를 열고 Examples 에서 예제를 선택합니다. 자세한 내용은 Qt Creator: 튜토리얼을 참조하세요 : 빌드 및 실행을 참조하세요.

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 유형을 사용하여 앱의 다양한 페이지를 표시합니다. 다른 페이지 구성 요소를 처리하는 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

    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 에서 "커피 선택"으로 상태가 변경되고 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
    }
    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.qmlGridLayout 로 전달됩니다.

CoffeeCards 이름, 추출 시간, 재료 및 현재 사용 가능한 컵 수에 따라 다릅니다.

이 페이지에서 사용자는 화면 오른쪽 상단의 작은 태양 모양의 아이콘 버튼을 눌러 처음으로 애플리케이션 테마를 변경할 수도 있습니다. 테마 버튼을 누르면 ApplicationFlow.qml 에서 themeButton 함수가 호출됩니다:

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

이 함수는 Colors.qmlcurrentTheme 속성을 변경하고 속성 바인딩에 따라 앱 전체에서 색상이 자동으로 변경됩니다. 앱에서 사용되는 모든 색상은 Colors.qml 에 있습니다.

테마가 밝은 테마로 전환되면 테마 변경 아이콘 버튼 아이콘이 반달 모양으로 바뀝니다.

커피 카드 중 하나를 누르면 CoffeeCard.qml 에서 AbstractButton 내부의 상태가 변경되고 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: (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 에 저장된 해당 값에 바인딩하여 확인합니다.

커피 컵을 채우는 애니메이션은 상태 엔진 TransitionSmoothedAnimation 에서 발생합니다.

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 으로 다시 이동합니다.

소스 파일

스퀴시 GUI 테스트

이 애플리케이션은 안드로이드용 Qt를 대상으로 하는 Squish GUI 테스트와 함께 제공됩니다. 테스트는 Squish for Qt로 작성되었으며 Python으로 작성되었으며 애플리케이션 테스트 디렉토리에서 찾을 수 있습니다.

Android용 Qt용 Squish를 사용할 때는 Qt에 내장된 후크를 사용하고 adb로 Squish 포트를 전달해야 합니다. dlopen 실패와 함께 "라이브러리를 로드할 수 없습니다"라는 오류가 발생하면 CMake 구성에서 QT_USE_TARGET_ANDROID_BUILD_DIR 을 비활성화하거나 Qt Creator 에서 Projects->Build Settings->CMake->Current Configuration 을 지웁니다.

Squish 라이선스가 없는 경우 무료 평가판을 받을 수 있습니다.

예제 프로젝트 @ code.qt.io

모든 Qt 예제를참조하세요 .

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