이 페이지에서

할 일 목록

모든 플랫폼에서 네이티브처럼 보이는 애플리케이션을 만드는 방법을 보여주는 할 일 목록 애플리케이션의 QML 구현체입니다.

'할 일 목록'은 모든 플랫폼에서 네이티브처럼 보이는 할 일 목록 애플리케이션의 예제를 보여줍니다. 이 예제는 Qt Design Studio 및 Qt Creator 에서 실행하고 편집할 수 있습니다. 이 예제는 사용자 정의 스타일을 생성하고 사용하는 방법과, 설정을 통해 애플리케이션의 외관 및 동작을 제어하는 방법을 보여줍니다. 또한 델리게이트에서 간단한 드래그 앤 드롭 동작을 구현하는 방법도 보여줍니다. 이 애플리케이션은 로컬 스토리지를 사용하여 기기에 항목을 저장하고, XMLHttpRequest를 사용하여 공개 API(Random Tasks 기능)에서 데이터를 가져옵니다. 뷰는 StackView 컴포넌트에 의해 제어됩니다.

예제 실행

다음 경로에서 예제를 실행할 수 있습니다.

모드

밝은 테마 사용자 지정 스타일

다크 테마 사용자 지정 스타일 다크 테마 설정 UI

Light Material 테마

다크 매터 테마 다크 머티리얼 테마 설정 UI

밝은 iOS 테마

iOS 다크 테마 다크 테마 설정 UI

앱 스타일 선택

이 애플리케이션은 대상 플랫폼에 따라 다양한 스타일을 지원합니다. 각 플랫폼(Windows, Android, iOS, macOS)에서 CustomStyle, Basic, Material 및 Universal 스타일을 사용할 수 있습니다. Windows 스타일은 Windows에서만, iOS 스타일은 iOS에서만 사용할 수 있습니다. 사용 가능한 스타일 목록은 ‘ SettingsView ’의 ‘Style’ 하위 페이지 중 하나에 있습니다. 현재 사용 중인 스타일은 같은 곳에서 변경할 수 있습니다. 변경 사항을 적용하려면 재시작이 필요합니다. 애플리케이션은 ‘ ToolTip ’ 알림을 통해 사용자에게 이를 안내합니다.

테마 변경

각 스타일에서는 다크 및 라이트 테마도 지원됩니다. 테마는 ‘ SettingsView ’의 ‘Theme’ 하위 페이지에서 변경할 수 있습니다. 모든 스타일에서 사용자가 수동으로 테마를 변경할 수 있는 것은 아닙니다. 예를 들어, iOS에서는 이 옵션을 사용할 수 없습니다. 이 경우 테마는 기본 시스템 설정에 따라 변경됩니다. 앱을 처음 실행할 때는 시스템 테마가 사용됩니다.

앱 설정에서 앱 동작 제어

SettingsView 에서 앱의 동작 및 스타일을 변경할 수 있습니다. 이 설정을 통해 사용자는 다음을 변경할 수 있습니다:

  • 스타일
  • 테마
  • 글꼴 크기
  • 최대 작업 수
  • 완료된 작업 자동 삭제 여부

작업 목록 구현

이 애플리케이션에는 세 가지 목록이 있습니다:

  • 오늘의 작업 목록 → 마감일이 오늘인 작업들.
  • 이번 주 작업 목록 → 향후 7일 이내에 마감일이 도래하는 작업들.
  • 나중 할 일 → 위 목록들에 포함되지 않는 할 일들.

작업들은 애플리케이션 시작 시 각 목록 모델에 할당됩니다. 물론, 작업은 실행 중(마감일이 변경될 때)에 목록 모델 간에 이동할 수 있습니다. 개별 목록의 정의는 TasksList.qml 및 TasksListForm.ui.qml 에서 이루어지며, 인스턴스는 TasksListsView.qml/TasksListsViewForm.ui.qml 에서 생성됩니다.

    ListModel {
        id: todayTasksListModel
    }

    ListModel {
        id: thisWeekTasksListModel
    }

    ListModel {
        id: laterTasksListModel
    }

    Column {
        id: column

        anchors.fill: parent
        spacing: 14

        TasksList {
            id: todayTasks

            width: column.width
            maxHeight: 180
            listModel: todayTasksListModel
            headerText: qsTr("Today")
            tasksCount: todayTasksListModel.count
        }

        TasksList {
            id: thisWeekTasks

            width: column.width
            maxHeight: column.height - y - 60
            listModel: thisWeekTasksListModel
            headerText: qsTr("This week")
            tasksCount: thisWeekTasksListModel.count
        }

        TasksList {
            id: laterTasks

            width: column.width
            maxHeight: column.height - y
            listModel: laterTasksListModel
            headerText: qsTr("Later")
            tasksCount: laterTasksListModel.count
        }
    }

리스트 모델에 데이터를 채우는 작업은 TasksListsView.qml 및 Component.onCompleted 에서 수행됩니다.

    function createTasksLists() : void {
        var tasks = Database.getTasks()
        var currentDate = new Date()
        var format = Qt.locale().dateFormat(Locale.LongFormat)
        var dateStr = currentDate.toLocaleDateString(Qt.locale(),format)
        tasks.forEach( function(task){
            if (task.date === dateStr) {
                todayTasksModel.append(task)
            } else if (checkThisWeekDate(task.date)) {
                thisWeekTasksModel.append(task)
            } else {
                laterTasksModel.append(task)
            }
        })
    }

    Component.onCompleted: createTasksLists()

스와이프, 드래그 앤 드롭 동작

목록 뷰는 TasksListDelegate 를 델리게이트로 사용합니다. 이 델리게이트는 SwipeDelegate 이며, 사용자가 항목을 스와이프하여 강조 표시(항목이 목록 맨 위로 이동)하거나 제거할 수 있게 해줍니다. 또한 사용자가 작업을 완료로 표시하거나(항목이 목록 맨 아래로 이동됨), 항목을 드래그 앤 드롭하여 목록의 특정 위치로 이동할 수도 있습니다. 이러한 동작의 구현은 ` TasksListDelegate.qml`에서 이루어집니다.

로컬 스토리지 사용

로컬 스토리지(Local Storage)는 작업 항목을 SQLite 데이터베이스에 읽고 쓰는 데 사용됩니다. 이 기능 및 기타 보조 함수의 구현은 싱글톤 객체인 Database.qml 에서 이루어집니다.

    property var _db

    function _database() {
        if (_db) return _db

        try {
            let db = LocalStorage.openDatabaseSync("ToDoList", "1.0", "ToDoList app database")

            db.transaction(function (tx) {
                tx.executeSql(`CREATE TABLE IF NOT EXISTS tasks (
                              task_id INTEGER PRIMARY KEY AUTOINCREMENT,
                              task_name,
                              task_dueDate TEXT,
                              task_dueTime TEXT,
                              task_notes TEXT,
                              done INTEGER,
                              highlighted INTEGER
                              )`);
            })

            _db = db
        } catch (error) {
            console.log("Error opening databse: " + error)
        };
        return _db
    }

    function addTask(taskName, taskDueDate, taskDueTime, taskNotes, taskDone, taskHighlighted) {
        let results
        root._database().transaction(function(tx){
            tx.executeSql(`INSERT INTO tasks (task_name, task_dueDate, task_dueTime,
                          task_notes, done, highlighted) VALUES(?,?,?,?,?,?);`,
                        [taskName, taskDueDate, taskDueTime, taskNotes, taskDone, taskHighlighted])
            results = tx.executeSql("SELECT * FROM tasks ORDER BY task_id DESC LIMIT 1")
        })
        return results.rows.item(0).task_id
    }

공개 API에서 데이터를 가져오기 위한 XMLHttpRequest 사용

XMLHttpRequest는 일부 공개 API에 요청을 전송하고 응답 데이터를 가져오는 데 사용됩니다. 이 애플리케이션은 수행할 임의의 작업을 반환할 수 있는 boredapi를 사용합니다. 그런 다음 해당 작업은 오늘의 작업 목록에 추가됩니다.

    function sendHttpRequest() : void {
        var http = new XMLHttpRequest()
        var url = "https://www.boredapi.com/api/activity";
        http.open("GET", url, true);

        http.setRequestHeader("Content-type", "application/json");
        http.setRequestHeader("Connection", "close");

        http.onreadystatechange = function() {
            if (http.readyState == 4) {
                if (http.status == 200) {
                    let object = JSON.parse(http.responseText.toString());
                    let currentDate = new Date()
                    let format = Qt.locale().dateFormat(Locale.LongFormat)
                    addTask(todayTasksModel, object.activity,
                            currentDate.toLocaleDateString(Qt.locale(), format), "","")
                } else {
                    console.log("Failed to fetch a random TODO item; the API provider might be down")
                }
            }
        }
        http.send();
    }

소스 파일

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

관련 항목: 모든 Qt 예제 및 Qt Quick 예제 및 튜토리얼.

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