在先前的例子中,我们可以“使用SQLite offline storage API来存储应用的设置”。我们也在例程“如何在QML应用中动态修改ListModel中的数据并存储它为JSON格式”中展示如何把我们需要的JSON存储到一个本地的文件中。在这篇文章中,我们将使用QtQuick所提供的LocalStorage来存储我们所需要的数据。
为了说明问题,我首先来创建一个基于“QtQuick App with QML UI (qmake)”的模版。首先我们修改我们的main.cpp如下:
Main.qml
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
qDebug() << "Local storage path: " << view.engine()->offlineStoragePath();
QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
view.setSource(QUrl(QStringLiteral("qrc:///Main.qml")));
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.show();
return app.exec();
}
Local storage path: "/home/phablet/.local/share/localstorage/QML/OfflineStorage"
这个路径显然是和我们在实际在手机上运行时产生的实际的路径是不同的:
这也说明在Ubuntu上的实现和标准的Qt上的实现还是不同的。从上面我们可以看出数据库的时间路径为:
phablet@ubuntu-phablet:~/.local/share/localstorage.liu-xiao-guo/Databases$ ls
4ff10001f402923590ceb1d12a0cffc6.ini 4ff10001f402923590ceb1d12a0cffc6.sqlite
为了能够使得应用能够自己退出,我们添加了如下的语句:
QObject::connect(view.engine(), SIGNAL(quit()), qApp, SLOT(quit()));
为了能够对SQLite数据库访问,我们设计了如下的database.js文件:
database.js
.import QtQuick.LocalStorage 2.0 as Sql
var db;
function initDatabase() {
print('initDatabase()')
db = Sql.LocalStorage.openDatabaseSync("CrazyBox", "1.0", "A box who remembers its position", 100000);
db.transaction( function(tx) {
print('... create table')
tx.executeSql('CREATE TABLE IF NOT EXISTS data(name TEXT, value TEXT)');
});
}
function readData() {
print('readData()')
if(!db) { return; }
db.transaction( function(tx) {
print('... read crazy object')
var result = tx.executeSql('select * from data where name="crazy"');
if(result.rows.length === 1) {
print('... update crazy geometry')
// get the value column
var value = result.rows[0].value;
// convert to JS object
var obj = JSON.parse(value)
// apply to object
crazy.x = obj.x;
crazy.y = obj.y;
}
});
}
function storeData() {
print('storeData()')
if(!db) { return; }
db.transaction( function(tx) {
print('... check if a crazy object exists')
var result = tx.executeSql('SELECT * from data where name = "crazy"');
// prepare object to be stored as JSON
var obj = { x: crazy.x, y: crazy.y };
if(result.rows.length === 1) {// use update
print('... crazy exists, update it')
result = tx.executeSql('UPDATE data set value=? where name="crazy"', [JSON.stringify(obj)]);
} else { // use insert
print('... crazy does not exists, create it')
result = tx.executeSql('INSERT INTO data VALUES (?,?)', ['crazy', JSON.stringify(obj)]);
}
});
}
这里,我们可以创建一个叫做“CrazyBox”的数据库,并在它里面生产一个叫做data的表。我们可以向表里更新数据。从这个例子里,我们可以看出来,用这个方法来存储我们的JSON数据而不使用到C++代码(参考例程“ 如何在QML应用中动态修改ListModel中的数据并存储它为JSON格式”)。这对大多数不很熟悉C++代码的开发者来说是一个好消息。
Main.qml
import QtQuick 2.0
import Ubuntu.Components 1.1
import "database.js" as DB
/*!
\brief MainView with a Label and Button elements.
*/
MainView {
// objectName for functional testing purposes (autopilot-qt5)
objectName: "mainView"
// Note! applicationName needs to match the "name" field of the click manifest
applicationName: "localstorage.liu-xiao-guo"
/*
This property enables the application to change orientation
when the device is rotated. The default is false.
*/
//automaticOrientation: true
// Removes the old toolbar and enables new features of the new header.
useDeprecatedToolbar: false
width: units.gu(60)
height: units.gu(85)
Page {
title: i18n.tr("Localstorage")
Rectangle {
id: crazy
objectName: 'crazy'
width: 200
height: 200
x: 50
y: 50
color: "#53d769"
border.color: Qt.lighter(color, 1.1)
Text {
anchors.centerIn: parent
text: Math.round(parent.x) + '/' + Math.round(parent.y)
}
MouseArea {
anchors.fill: parent
drag.target: parent
}
}
Component.onCompleted: {
DB.initDatabase();
print("it is going to read data");
DB.readData();
}
Component.onDestruction: {
print("it is going to save data");
DB.storeData();
}
Button {
anchors.bottom: parent.bottom
anchors.bottomMargin: units.gu(1)
anchors.horizontalCenter: parent.horizontalCenter
text: "Close"
onClicked: {
Qt.quit();
}
}
}
}
我们的Main.qml设计非常简单。我们在UI被装载完后,初始化数据库,并读取已经存储的数据。如果数据已经存在,就读出来,并初始化我们的Rectangle “crazy”。在应用退出的时候,我们存储我们的数据。这里应该注意的是,当我们用我们的手指拖动关掉应用时,我们的应用接受不到如下的事件:
Component.onDestruction: {
print("it is going to save data");
DB.storeData();
}
我们必须通过选择“Quit”按钮来得到这个事件。
运行我们的应用:
每当我们退出应用,并重新启动应用后,我们可以发现我们的绿色的方块是在和上次退出时一样的位置。