๐๊ธฐ๋ฅ์ ๋ฒํผ ํด๋ฆญํ๋ฉด ํ
์คํธ ์
๋ ฅ 2๊ฐ์ ์
๋ ฅ๋ ์ ๋ณด๋ฅผ ๋ก์ปฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ณ ๋ฆฌ์คํธ๋ทฐ์ ํ์ํด์ค๋๋ค.
The function saves the information entered in the two text inputs to a local database when the button is clicked and displays it in a list view.
๐ QML์์ฒด๊ฐ ๋ก์ปฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋๊ธฐ๋ฅ์ด ์์ต๋๋ค.
QML itself has a local database connection function.
๐ํ๋ก์ ํธ์์ฑ ํ ์์ ํด์ผํ ๊ฑด Main.qml๊ณผ Screen01.qml,CMakeLists.txt์
๋๋ค.
After creating the project, the files that need to be modified are Main.qml, Screen01.qml, and CMakeLists.txt.
๐CMakeLists.txtํ์ผ์์ Screen01.qml์ ์ธ์ํ๋๋ก ์ค์ ํฉ๋๋ค.
Set the CMakeLists.txt file to recognize Screen01.qml.
๐Main.qml์ Screen01.qml์ ๋ถ๋ฌ์ค๋ ์ญํ ๋ง ์ํํฉ๋๋ค.
Main.qml only performs the role of loading Screen01.qml.
๐๋ชจ๋ ๋ฐ์ดํฐ์ฒ๋ฆฌ์ ์ฑ๋์์ธ์ Screen01.qml์์ ์ํํฉ๋๋ค.
All data processing and app design is performed in Screen01.qml.
1.CMakeLists.txt
โ๏ธ ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ๋ด์ qml/Screen01.qml ํ์ผ์ ๋ง๋ญ๋๋ค.
Create a file named qml/Screen01.qml in the project directory.
โ๏ธ qml/Screen01.qml ์ด ์ฝ๋๋ง ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
Just add this code to qml/Screen01.qml.
cmake_minimum_required(VERSION 3.16)
project(example5 VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Quick)
#--
find_package(Qt6 6.5 COMPONENTS Quick REQUIRED)
qt_standard_project_setup(REQUIRES 6.8)
qt_add_executable(appexample5
main.cpp
)
qt_add_qml_module(appexample5
URI example5
VERSION 1.0
QML_FILES
Main.qml
qml/Screen01.qml
)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appexample5 PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appexample5
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appexample5
PRIVATE Qt6::Quick
)
include(GNUInstallDirs)
install(TARGETS appexample5
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
2.Main.qml
โ๏ธ ๋ณผ๋์ฒด ์ค์ ๋ ๋ถ๋ถ์ ์ฝ๋๋ง ์
๋ ฅํ๋ฉด ๋ฉ๋๋ค.
You only need to enter the code for the bolded part.
import QtQuick
import QtQuick.Controls
import QtQuick.Window
Window {
width: 800
height: 600
visible: true
title: qsTr("QML LocalStorage Example")
Loader {
anchors.fill: parent
source: "qml/Screen01.qml" // ๋ก์ปฌ QML ํ์ผ ๋ก๋ / Local QML file load
}
}
3.qml/Screen01.qml
โ๏ธ์ฌ๊ธฐ์ ๋ฐ์ดํฐ ์
๋ ฅ, ์์ , ์ญ์ ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
This is where you enter, edit, and delete data.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.LocalStorage
Rectangle {
id: root
width: 800
height: 600
color: "#EAEAEA"
property var db
property int selectedId: -1 // ์ ํ๋ ๋ ์ฝ๋ ID / Seclected Record ID
Component.onCompleted: {
db = LocalStorage.openDatabaseSync("ExampleLocalDB", "1.0", "Local DB Example", 1000000)
db.transaction(function(tx) {
tx.executeSql("CREATE TABLE IF NOT EXISTS records(id INTEGER PRIMARY KEY AUTOINCREMENT, text1 TEXT, text2 TEXT)")
})
loadData()
}
// DB์์ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
// Retrieving data from DB
function loadData() {
db.transaction(function(tx) {
const rs = tx.executeSql("SELECT * FROM records ORDER BY id DESC")
listModel.clear()
for (let i = 0; i < rs.rows.length; i++) {
listModel.append({
id: rs.rows.item(i).id,
text1: rs.rows.item(i).text1,
text2: rs.rows.item(i).text2
})
}
selectedId = -1
})
}
// DB์ ์ ๋ฐ์ดํฐ ์ถ๊ฐ
// Add new data to DB
function insertData(t1, t2) {
if (t1.trim() === "" || t2.trim() === "") {
console.log("์
๋ ฅ๊ฐ์ด ๋น์ด ์์ต๋๋ค.")
return
}
db.transaction(function(tx) {
tx.executeSql("INSERT INTO records (text1, text2) VALUES (?, ?)", [t1, t2])
})
input1.text = ""
input2.text = ""
loadData()
}
// ์ ํ๋ ๋ ์ฝ๋ ์ญ์
// Delete selected record
function deleteSelected() {
if (selectedId === -1) return
db.transaction(function(tx) {
tx.executeSql("DELETE FROM records WHERE id = ?", [selectedId])
})
loadData()
}
// DB์ ๋ชจ๋ ๋ฐ์ดํฐ ์ญ์
// Delete all data in DB
function deleteAllData() {
db.transaction(function(tx) {
tx.executeSql("DELETE FROM records")
})
loadData()
}
ColumnLayout {
anchors.centerIn: parent
spacing: 12
width: 300
// ๋ฆฌ์คํธ ๋ทฐ / List View
Rectangle {
Layout.fillWidth: true
height: 250
color: "white"
border.color: "#B0B0B0"
radius: 4
ListView {
id: listView
// ๋ถ๋ชจ Reactangleํฌ๊ธฐ์ ๊ฐ๊ฒ ์ค์
// Set the size to be the same as the parent Reactangle
anchors.fill: parent
// ๋ถ๋ชจ Rectangle์ ๊ฒฝ๊ณ ์์ชฝ์ผ๋ก 4px ์ฌ์
// Rectangleํ
๋๋ฆฌ๊ฐ ์๋ณด์ด๊ธฐ๋๋ฌธ์
// 4px margin inside the parent Rectangle's border
// Because the Rectangle border is not visibl
anchors.margins: 4
clip: true
model: ListModel { id: listModel }
interactive: true
highlightFollowsCurrentItem: true
currentIndex: -1
delegate: Rectangle {
id: delegateRect
height: 36
width: listView.width
//anchors.fill: parent
//anchors.margins: 6
//anchors.left: parent.left
//anchors.right: parent.right
// ๋ ์ฝ๋์ ๋ณ๊ฒฝ / Change record color
color: listView.currentIndex === index ? "#D0E6FF" : (index % 2 === 0 ? "#FFFFFF" : "#FFFFFF")
// -- ์ค๋ฌด๋ฌ ํํ ์ ์ฉ / Apply striped shape
//color: listView.currentIndex === index ? "#D0E6FF" : (index % 2 === 0 ? "#F9F9F9" : "#FFFFFF")
Row {
anchors.fill: parent
anchors.margins: 6
spacing: 10
Text { text: text1; font.pixelSize: 14; color: "black" }
Text { text: text2; font.pixelSize: 14; color: "gray" }
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index
root.selectedId = id
}
}
}
}
}
// ์
๋ ฅ ํ๋ / input field
TextField { id: input1; Layout.fillWidth: true; placeholderText: "ํ
์คํธ1 ์
๋ ฅ/text1 input" }
TextField { id: input2; Layout.fillWidth: true; placeholderText: "ํ
์คํธ2 ์
๋ ฅ/text2 input" }
// ๋ฒํผ ์์ญ / button area
RowLayout {
Layout.fillWidth: true
spacing: 10
Button {
text: "์ ์ฅ/Save"
Layout.fillWidth: true
onClicked: insertData(input1.text, input2.text)
}
Button {
text: "์ญ์ /Delete"
Layout.fillWidth: true
enabled: selectedId !== -1
onClicked: deleteSelected()
}
Button {
text: "๋ชจ๋์ญ์ /DeleteAll"
Layout.fillWidth: true
onClicked: deleteAllData()
}
}
}
}