我想在QT Quick中使用SQLite数据库,但找不到任何示例。我只是想能够从数据库中访问项目。是否有人知道我可以尝试的示例程序?
定义角色名称,委托将通过角色在QtQuick组件中访问数据(data
方法有点天真,因为没有任何错误检查):
class SqlQueryModel: public QSqlQueryModel
{
Q_OBJECT
QHash<int,QByteArray> *hash;
public:
explicit SqlQueryModel(QObject * parent) : QSqlQueryModel(parent)
{
hash = new QHash<int,QByteArray>;
hash->insert(Qt::UserRole, QByteArray("someRoleName"));
hash->insert(Qt::UserRole + 1, QByteArray("otherRoleName"));
}
QVariant data(const QModelIndex &index, int role) const
{
if(role < Qt::UserRole) {
return QSqlQueryModel::data(index, role);
}
QSqlRecord r = record(index.row());
return r.value(QString(hash->value(role))).toString();
}
inline RoleNameHash roleNames() const { return *hash; }
};
创建新定义的模型类的实例并将其添加到QML上下文中。
view = new QQuickView();
QSqlQueryModel *someSqlModel = new SqlQueryModel(this);
someSqlModel->setQuery("SELECT someRoleName, otherRoleName FROM some_table");
QQmlContext *context = view->rootContext();
context->setContextProperty("someSqlModel", someSqlModel);
view->setSource(QUrl("qrc:///MainView.qml"));
view->show();
将您的模型绑定到ListView的model
属性,并使用先前定义的角色名称来访问委托中的数据。
ListView {
id: someListView
model: someSqlModel
delegate: Text {
anchors.fill: parent
text: someRoleName
}
}
Rebus的回答是一个很好的开始,但我还想知道如何连接到现有的(SQLite)数据库。
所以这里是一个完整的例子,适用于Qt 5.x,不需要任何先决条件。
请注意,代码在SqlModel.data()中避免了角色名称哈希表查找和所有多余的堆分配。
主.cpp
#include <QtDebug>
#include <QString>
#include <QHash>
#include <QGuiApplication>
#include <QtQml>
#include <QQuickView>
#include <QtSql>
#include <QSqlQueryModel>
QSqlError initDb()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
// Open database file. The driver creates a new file if it doesn't exist yet.
db.setDatabaseName("mylibrary.sqlite");
if (!db.open())
return db.lastError();
QStringList tables = db.tables();
if (tables.contains("books", Qt::CaseInsensitive)) {
// DB has already been populated
return QSqlError();
}
QSqlQuery query;
if (!query.exec(QLatin1String("create table books(title varchar, author varchar)")))
return query.lastError();
if (!query.prepare(QLatin1String("insert into books(title, author) values(?, ?)")))
return query.lastError();
auto addBook = [&] (const QString& title, const QString& author) {
query.addBindValue(title);
query.addBindValue(author);
query.exec();
};
addBook("Mademoiselle de Maupin", "T. Gautier");
addBook("Der Nachsommer", "A. Stifter");
addBook("L'Education sentimentale", "G. Flaubert");
addBook("Voyna i mir", "L. Tolstoy");
addBook("Mysterier", "K. Hamsun");
addBook("The Sound and the Fury", "W. Faulkner");
addBook("Tender is the Night", "F. Scott Fitzgerald");
return QSqlError();
}
class SqlModel : public QSqlQueryModel
{
Q_OBJECT
public:
SqlModel(QObject* parent = 0)
: QSqlQueryModel(parent)
{
roleNamesHash.insert(Qt::UserRole, QByteArray("title"));
roleNamesHash.insert(Qt::UserRole + 1, QByteArray("author"));
}
QVariant data(const QModelIndex& index, int role) const
{
if(role < Qt::UserRole)
return QSqlQueryModel::data(index, role);
QSqlRecord r = record(index.row());
return r.value(role - Qt::UserRole);
}
QHash<int, QByteArray> roleNames() const { return roleNamesHash; }
private:
QHash<int, QByteArray> roleNamesHash;
};
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
auto err = initDb();
if (err.type() != QSqlError::NoError) {
qCritical() << err.text();
return 1;
}
SqlModel sqlModel;
sqlModel.setQuery("SELECT title, author FROM books");
QQuickView view;
QQmlContext *context = view.rootContext();
context->setContextProperty("sqlModel", &sqlModel);
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:///main.qml"));
view.show();
return app.exec();
}
#include "main.moc"
main.qml
import QtQuick 2.1
Item {
width: 500
height: 300
ListView {
anchors { fill: parent; margins: 20 }
model: sqlModel
delegate: Text {
text: author + ' - ' + title
}
}
}
resources.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
minimal-qml-sql-app.pro
CONFIG += c++11
QT += qml \
quick \
sql
SOURCES += main.cpp
OTHER_FILES += main.qml
RESOURCES += resources.qrc
与Rebus和Kay的答案相比,有一个有趣的注释:日历示例使用Examples/Qt-5.3/quick/controls/calendar
公开SqlModel。这允许更具声明性的编程风格:无需在main.cpp中实例化SqlModel,而是在qml中声明它。qmlRegisterType()
Calendar
已经有了自己的模型(用于月份中的天数)。相反,它只是获取特定日期的事件列表(QList<QObject*>
模型)。由于这个事实,它最近被更改为简单地成为一个QObject
:https://codereview.qt-project.org/#/c/145253/ - Mitch
QSqlQueryModel
使得定义SqlQueryModel
没有意义,而且这个例子可能不会工作,因为 QML 找不到someRoleName
角色。 - Davor Lucic