{"id":2422,"date":"2025-10-15T11:07:33","date_gmt":"2025-10-15T02:07:33","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=2422"},"modified":"2025-10-16T10:18:30","modified_gmt":"2025-10-16T01:18:30","slug":"qtexample5-cqml-databasesqlite","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2025\/10\/15\/qtexample5-cqml-databasesqlite\/","title":{"rendered":"[QT]example6-C++,QML-database(SQLite)"},"content":{"rendered":"\n<p>\ud83d\udc49 QML\uc740 \ub514\uc790\uc778\uc744 \ub2f4\ub2f9\ud558\uace0 C++\uc774 \ub370\uc774\ud130 \ucc98\ub9ac\ub97c \ub2f4\ub2f9\ud569\ub2c8\ub2e4.<br>QML handles the design and C++ handles the data processing.<\/p>\n\n\n\n<p>\ud83d\udc49 qt_add_excutable\ud568\uc218\ub294 exe\ud30c\uc77c\uc744 \ub9cc\ub4e4\ub54c \ud544\uc694\ud55c cpp\ud30c\uc77c \ub9ac\uc2a4\ud2b8\uc785\ub2c8\ub2e4.<br>The qt_add_executable function is a list of cpp files required when creating an exe file.<\/p>\n\n\n\n<p><strong>1.CMakeLists.txt<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cmake_minimum_required(VERSION 3.16)\n\nproject(example6 VERSION 0.1 LANGUAGES CXX)\n\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n\nfind_package(Qt6 REQUIRED COMPONENTS Quick)\n\n#--sqlite\n<strong>find_package(Qt6 REQUIRED COMPONENTS Quick Sql)<\/strong>\n\n\nqt_standard_project_setup(REQUIRES 6.8)\n\n#-- making .exe file list\nqt_add_executable(appexample6\n    main.cpp\n    #--sqlite\n   <strong> databasemanager.cpp<\/strong>\n)\n\nqt_add_qml_module(appexample6\n    URI example6\n    VERSION 1.0\n    QML_FILES\n        Main.qml\n        #-- \ucd94\uac00\/Add\n        <strong>qml\/Screen01.qml<\/strong>\n        SOURCES Databasemanager.h Databasemanager.cpp\n)\n\n# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.\n# If you are developing for iOS or macOS you should consider setting an\n# explicit, fixed bundle identifier manually though.\nset_target_properties(appexample6 PROPERTIES\n#    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appexample6\n    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}\n    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}\n    MACOSX_BUNDLE TRUE\n    WIN32_EXECUTABLE TRUE\n)\n#-- sqlite\n<strong>target_link_libraries(appexample6\n    PRIVATE Qt6::Quick Qt6::Sql\n)<\/strong>\n\ntarget_link_libraries(appexample6\n    PRIVATE Qt6::Quick\n)\n\ninclude(GNUInstallDirs)\ninstall(TARGETS appexample6\n    BUNDLE DESTINATION .\n    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}\n    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n)\n<\/code><\/pre>\n\n\n\n<p><strong>2.databasemanager.h<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifndef DATABASEMANAGER_H\n#define DATABASEMANAGER_H\n\n#include &lt;QObject&gt;\n#include &lt;QSqlDatabase&gt;\n#include &lt;QSqlQuery&gt;\n#include &lt;QSqlError&gt;\n#include &lt;QVariantList&gt;\n#include &lt;QDebug&gt;\n\nclass DatabaseManager : public QObject {\n    Q_OBJECT\npublic:\n    explicit DatabaseManager(QObject *parent = nullptr);\n    Q_INVOKABLE bool insertData(const QString &amp;text1, const QString &amp;text2);\n    Q_INVOKABLE QVariantList loadData();\n    Q_INVOKABLE bool deleteData(int id);\n    Q_INVOKABLE bool deleteAll();\n\nprivate:\n    QSqlDatabase db;\n    void initialize();\n};\n\n#endif \/\/ DATABASEMANAGER_H<\/code><\/pre>\n\n\n\n<p><strong>3.databasemanager.cpp<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"DatabaseManager.h\"\n\nDatabaseManager::DatabaseManager(QObject *parent)\n    : QObject(parent)\n{\n    db = QSqlDatabase::addDatabase(\"QSQLITE\");\n    db.setDatabaseName(\"localdata.db\");\n\n    if (!db.open()) {\n        qWarning() &lt;&lt; \"Database open error:\" &lt;&lt; db.lastError().text();\n        return;\n    }\n\n    initialize();\n    qDebug() &lt;&lt; \"\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ucd08\uae30\ud654 \uc2e4\ud589\/Run database initialization\";\n}\n\n\/\/ \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ucd08\uae30\ud654 \/ database initialize\nvoid DatabaseManager::initialize() {\n    QSqlQuery query;\n    query.exec(\"CREATE TABLE IF NOT EXISTS records (\"\n               \"id INTEGER PRIMARY KEY AUTOINCREMENT, \"\n               \"text1 TEXT, \"\n               \"text2 TEXT)\");\n}\n\/\/ \uc785\ub825 \/ input\nbool DatabaseManager::insertData(const QString &amp;text1, const QString &amp;text2) {\n    QSqlQuery query;\n    query.prepare(\"INSERT INTO records (text1, text2) VALUES (?, ?)\");\n    query.addBindValue(text1);\n    query.addBindValue(text2);\n    bool ok = query.exec();\n    if (!ok) qWarning() &lt;&lt; \"Insert failed:\" &lt;&lt; query.lastError().text();\n    return ok;\n}\n\n\/\/ \ub370\uc774\ud130 \ub85c\ub529 \/ data loading\nQVariantList DatabaseManager::loadData() {\n    QVariantList list;\n    QSqlQuery query(\"SELECT id, text1, text2 FROM records ORDER BY id DESC\");\n    while (query.next()) {\n        QVariantMap item;\n        item&#91;\"id\"] = query.value(0).toInt();\n        item&#91;\"text1\"] = query.value(1).toString();\n        item&#91;\"text2\"] = query.value(2).toString();\n        list.append(item);\n    }\n    return list;\n}\n\/\/ \uc0ad\uc81c \/ data Delete\nbool DatabaseManager::deleteData(int id) {\n    QSqlQuery query;\n    query.prepare(\"DELETE FROM records WHERE id = ?\");\n    query.addBindValue(id);\n    bool ok = query.exec();\n    if (!ok) qWarning() &lt;&lt; \"Delete failed:\" &lt;&lt; query.lastError().text();\n    return ok;\n}\n\/\/ \ubaa8\ub450 \uc0ad\uc81c \/delete all data\nbool DatabaseManager::deleteAll() {\n    QSqlQuery query(\"DELETE FROM records\");\n    return query.exec();\n}\n<\/code><\/pre>\n\n\n\n<p><strong>4.qml\/Screen01.qml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import QtQuick\nimport QtQuick.Controls\nimport QtQuick.Layouts\n\nRectangle {\n    id: root\n    width: 800\n    height: 600\n    color: \"#EAEAEA\"\n\n    property int selectedId: -1\n\n    ColumnLayout {\n        anchors.centerIn: parent\n        spacing: 12\n        width: 300\n\n        \/\/ \ub9ac\uc2a4\ud2b8\ubdf0 \/ ListView\n        Rectangle {\n            Layout.fillWidth: true\n            height: 250\n            color: \"white\"\n            border.color: \"#B0B0B0\"\n            radius: 4\n\n            ListView {\n                id: listView\n                anchors.fill: parent\n                anchors.margins: 4\n                clip: true\n                model: ListModel { id: listModel }\n                interactive: true\n                currentIndex: -1\n\n                delegate: Rectangle {\n                    height: 36\n                    width: listView.width\n                    \/\/color: listView.currentIndex === index ? \"#D0E6FF\" : (index % 2 === 0 ? \"#FFFFFF\" : \"#F9F9F9\")\n                    color: listView.currentIndex === index ? \"#D0E6FF\" : (index % 2 === 0 ? \"#FFFFFF\" : \"#FFFFFF\")\n\n                    Row {\n                        anchors.fill: parent\n                        anchors.margins: 6\n                        spacing: 10\n                        Text { text: text1; font.pixelSize: 14; color: \"black\" }\n                        Text { text: text2; font.pixelSize: 14; color: \"gray\" }\n                    }\n\n                    MouseArea {\n                        anchors.fill: parent\n                        onClicked: {\n                            listView.currentIndex = index\n                            root.selectedId = id\n                        }\n                    }\n                }\n            }\n        }\n\n        \/\/ \uc785\ub825 \ud544\ub4dc \/ input field\n        TextField { id: input1; Layout.fillWidth: true; placeholderText: \"\ud14d\uc2a4\ud2b81 \uc785\ub825\/text input1\" }\n        TextField { id: input2; Layout.fillWidth: true; placeholderText: \"\ud14d\uc2a4\ud2b82 \uc785\ub825\/text input2\" }\n\n        \/\/ \ubc84\ud2bc \/ button\n        RowLayout {\n            Layout.fillWidth: true\n            spacing: 10\n\n            Button {\n                text: \"\uc800\uc7a5\/Save\"\n                Layout.fillWidth: true\n                onClicked: {\n                    if (input1.text.length === 0 || input2.text.length === 0)\n                        return\n                    DB.insertData(input1.text, input2.text)\n                    refreshList()\n                    input1.text = \"\"\n                    input2.text = \"\"\n                }\n            }\n\n            Button {\n                text: \"\uc0ad\uc81c\/Delete\"\n                Layout.fillWidth: true\n                enabled: root.selectedId !== -1\n                onClicked: {\n                    DB.deleteData(root.selectedId)\n                    root.selectedId = -1\n                    refreshList()\n                }\n            }\n\n            Button {\n                text: \"\ubaa8\ub450\uc0ad\uc81c\/Delete All\"\n                Layout.fillWidth: true\n                onClicked: {\n                    DB.deleteAll()\n                    refreshList()\n                }\n            }\n        }\n    }\n\n    \/\/ \ub370\uc774\ud130 \uc0c8\ub85c\uace0\uce68 \/ data refresh\n    function refreshList() {\n        listModel.clear()\n        const data = DB.loadData()\n        for (let i = 0; i &lt; data.length; i++) {\n            listModel.append({\n                id: data&#91;i].id,\n                text1: data&#91;i].text1,\n                text2: data&#91;i].text2\n            })\n        }\n    }\n\n    Component.onCompleted: refreshList()\n}\n<\/code><\/pre>\n\n\n\n<p><strong>5.main.cpp<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;QGuiApplication&gt;\n#include &lt;QQmlApplicationEngine&gt;\n\n\/\/\ucf54\ub4dc\ucd94\uac00 \/ Add code\n#include &lt;QQmlContext&gt;          \/\/ QML\uacfc C++ \uc5f0\uacb0\uc6a9 \/ For connecting QML and C++\n#include \"DatabaseManager.h\"    \/\/ database\n\nint main(int argc, char *argv&#91;])\n{\n    QGuiApplication app(argc, argv);\n\n    QQmlApplicationEngine engine;\n\n\n    QObject::connect(\n        &amp;engine,\n        &amp;QQmlApplicationEngine::objectCreationFailed,\n        &amp;app,\n        &#91;]() { QCoreApplication::exit(-1); },\n        Qt::QueuedConnection);\n\n\n    \/\/ DatabaseManager \uc778\uc2a4\ud134\uc2a4 \uc0dd\uc131\n    \/\/ Create a DatabaseManager instance\n    static DatabaseManager dbManager;\n\n\n    \/\/ QML \uc804\uc5ed \ucee8\ud14d\uc2a4\ud2b8\uc5d0 \ub4f1\ub85d\n    \/\/ Register in the QML global context\n    engine.rootContext()-&gt;setContextProperty(\"DB\", &amp;dbManager);\n\n    \/\/\n    engine.loadFromModule(\"example6\", \"Main\");\n\n    return app.exec();\n}\n\n<\/code><\/pre>\n\n\n\n<p><strong>6.main.qml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import QtQuick\n\nWindow {\n    width: 640\n    height: 480\n    visible: true\n    title: qsTr(\"Hello World\")\n    Loader {\n        anchors.fill: parent\n        source: \"qml\/Screen01.qml\"  \/\/ \ub85c\uceec QML \ud30c\uc77c \ub85c\ub4dc \/ Local QML file load\n    }\n}\n<\/code><\/pre>\n\n\n\n<p><strong>7.\uc2e4\ud589 \/ run<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"638\" height=\"508\" src=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/10\/example-6.png\" alt=\"\" class=\"wp-image-2433\" srcset=\"https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/10\/example-6.png 638w, https:\/\/www.freelifemakers.org\/wordpress\/wp-content\/uploads\/2025\/10\/example-6-300x239.png 300w\" sizes=\"auto, (max-width: 638px) 100vw, 638px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49 QML\uc740 \ub514\uc790\uc778\uc744 \ub2f4\ub2f9\ud558\uace0 C++\uc774 \ub370\uc774\ud130 \ucc98\ub9ac\ub97c \ub2f4\ub2f9\ud569\ub2c8\ub2e4.QML handles the design and C++ handles the data processing. \ud83d\udc49 qt_add_excutable\ud568\uc218\ub294 exe\ud30c\uc77c\uc744 \ub9cc\ub4e4\ub54c \ud544\uc694\ud55c cpp\ud30c\uc77c \ub9ac\uc2a4\ud2b8\uc785\ub2c8\ub2e4.The qt_add_executable function is a list of cpp files required when creating an exe file. 1.CMakeLists.txt 2.databasemanager.h 3.databasemanager.cpp 4.qml\/Screen01.qml 5.main.cpp 6.main.qml 7.\uc2e4\ud589 \/ run<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,1],"tags":[],"class_list":["post-2422","post","type-post","status-publish","format-standard","hentry","category-qt","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2422","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=2422"}],"version-history":[{"count":13,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2422\/revisions"}],"predecessor-version":[{"id":2454,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/2422\/revisions\/2454"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=2422"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=2422"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=2422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}