子类化 QSqlTableModel 插入新值
Subclassing QSqlTableModel insert new value
我想在 QML-Tableview 中显示来自本地 db-File 的 SQL 数据,而不是想对 sql- 数据库进行一些编辑。
大约三周后我设法做到了:在 QML-Tableview 中显示我的数据。我不确定我是否真的需要对 QSqlTableModel 进行子类化,如果根本不需要子类化,我肯定会很高兴。
在我的main.cpp下面应该创建我的模型,直接添加一条记录。
// Create an instance of the SqlModel for accessing the data
SqlDataModel *sqlModel;
sqlModel = new SqlDataModel(0,base.database());
sqlModel->setTable("diaBaneDatabase");
sqlModel->setSort(0, Qt::AscendingOrder);
sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange);
sqlModel->select();
QSqlRecord record(sqlModel->record());
record.setValue(0,50);
record.setValue(3,222);
sqlModel->insertRecord(-1, record);
sqlModel->submitAll();
这应该将 222 添加到第 4 列。但是我的sql数据库
中不会存储任何内容
我的 SqlDataModel::setData 看起来像这样:
bool SqlDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
qDebug() << index.column() << " " << index.row() << " " << value << " ---- " << role;
qDebug() << roles[Qt::UserRole + 1];
//qDebug() << QSqlTableModel::setData(modelIndex, value);
qDebug() << QSqlQueryModel::setData(index, value);
return false;
}
输出将是:
0 39 QVariant(int, 50) ---- 2
"id"
false
1 39 QVariant(QString, "") ---- 2
"id"
false
2 39 QVariant(QString, "") ---- 2
"id"
false
3 39 QVariant(int, 222) ---- 2
"id"
false
4 39 QVariant(double, 0) ---- 2
"id"
false
5 39 QVariant(int, 0) ---- 2
"id"
false
6 39 QVariant(double, 0) ---- 2
"id"
false
7 39 QVariant(double, 0) ---- 2
"id"
false
确定我的 setData 方法是错误的,但我不明白那里应该发生什么,我没有找到任何例子。
我的假设是否错误,即我需要子类化 QSqlTableModel 以便能够通过 QQmlContext 将模型放入 QML,而不是显示具有像我的列命名一样命名的角色的列?如果不是,我如何将第 1 列的内容放入 QMLTableview:
TableViewColumn {
role: "id" // what should be the role if I don't subclass???
title: "ID"
width: 80
}
我很高兴得到任何帮助、评论、示例、其他帖子或任何让我更进一步的东西......谢谢
我一直在研究一个例子。
一些注意事项:
- QML 项目,例如
TableView
需要一个模型,所以我认为 QSqlTableModel
是一个很好的选择。当然,you have other models可以用来处理数据项。
- 在 class
MySqlTableModel
中您将看到所需的角色名称。 MySqlTableModel
重新实现 roleNames()
以公开角色名称,以便可以通过 QML 访问它们。
- 您可以在
MySqlTableModel
中重新实现setData
方法,但我认为最好使用QSqlTableModel
提供的方法insertRecord
。
我希望这个例子能帮助您改正错误。
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "mysqltablemodel.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydb");
if(!db.open()) {
qDebug() << db.lastError().text();
return 0;
}
QSqlQuery query(db);
if(!query.exec("DROP TABLE IF EXISTS mytable")) {
qDebug() << "create table error: " << query.lastError().text();
return 0;
}
if(!query.exec("CREATE TABLE IF NOT EXISTS mytable \
(id integer primary key autoincrement, name varchar(15), salary integer)")) {
qDebug() << "create table error: " << query.lastError().text();
return 0;
}
MySqlTableModel *model = new MySqlTableModel(0, db);
model->setTable("mytable");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
QSqlRecord rec = model->record();
rec.setValue(1, "peter");
rec.setValue(2, 100);
model->insertRecord(-1, rec);
rec.setValue(1, "luke");
rec.setValue(2, 200);
model->insertRecord(-1, rec);
if(model->submitAll()) {
model->database().commit();
} else {
model->database().rollback();
qDebug() << "database error: " << model->lastError().text();
}
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("myModel", model);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
mysqltablemodel.h
#ifndef MYSQLTABLEMODEL_H
#define MYSQLTABLEMODEL_H
#include <QSqlTableModel>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlQuery>
#include <QDebug>
class MySqlTableModel : public QSqlTableModel
{
Q_OBJECT
public:
MySqlTableModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
Q_INVOKABLE QVariant data(const QModelIndex &index, int role=Qt::DisplayRole ) const;
Q_INVOKABLE void addItem(const QString &name, const QString &salary);
protected:
QHash<int, QByteArray> roleNames() const;
private:
QHash<int, QByteArray> roles;
};
#endif // MYSQLTABLEMODEL_H
mysqltablemodel.cpp
#include "mysqltablemodel.h"
MySqlTableModel::MySqlTableModel(QObject *parent, QSqlDatabase db): QSqlTableModel(parent, db) {}
QVariant MySqlTableModel::data ( const QModelIndex & index, int role ) const
{
if(index.row() >= rowCount()) {
return QString("");
}
if(role < Qt::UserRole) {
return QSqlQueryModel::data(index, role);
}
else {
return QSqlQueryModel::data(this->index(index.row(), role - Qt::UserRole), Qt::DisplayRole);
}
}
QHash<int, QByteArray> MySqlTableModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Qt::UserRole + 1] = "name";
roles[Qt::UserRole + 2] = "salary";
return roles;
}
void MySqlTableModel::addItem(const QString &name, const QString &salary)
{
QSqlRecord rec = this->record();
rec.setValue(1, name);
rec.setValue(2, salary.toInt());
this->insertRecord(-1, rec);
if(this->submitAll()) {
this->database().commit();
} else {
this->database().rollback();
qDebug() << "database error: " << this->lastError().text();
}
}
main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
TableView {
id: tableView
anchors.fill: parent
TableViewColumn {
role: "name"
title: "Name"
width: 200
}
TableViewColumn {
role: "salary"
title: "Salary"
width: 200
}
model: myModel
}
Button {
id: addButton
anchors.verticalCenter: parent.verticalCenter
text: "Add item"
onClicked: {
if (nameBox.text || salaryBox.text) {
myModel.addItem(nameBox.text, salaryBox.text)
}
}
}
TextField {
id: nameBox
placeholderText: "name"
anchors.verticalCenter: parent.verticalCenter
anchors.left: addButton.right
anchors.leftMargin: 5
}
TextField {
id: salaryBox
placeholderText: "salary"
anchors.verticalCenter: parent.verticalCenter
anchors.left: nameBox.right
anchors.leftMargin: 5
}
}
我想在 QML-Tableview 中显示来自本地 db-File 的 SQL 数据,而不是想对 sql- 数据库进行一些编辑。 大约三周后我设法做到了:在 QML-Tableview 中显示我的数据。我不确定我是否真的需要对 QSqlTableModel 进行子类化,如果根本不需要子类化,我肯定会很高兴。
在我的main.cpp下面应该创建我的模型,直接添加一条记录。
// Create an instance of the SqlModel for accessing the data
SqlDataModel *sqlModel;
sqlModel = new SqlDataModel(0,base.database());
sqlModel->setTable("diaBaneDatabase");
sqlModel->setSort(0, Qt::AscendingOrder);
sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange);
sqlModel->select();
QSqlRecord record(sqlModel->record());
record.setValue(0,50);
record.setValue(3,222);
sqlModel->insertRecord(-1, record);
sqlModel->submitAll();
这应该将 222 添加到第 4 列。但是我的sql数据库
中不会存储任何内容我的 SqlDataModel::setData 看起来像这样:
bool SqlDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
qDebug() << index.column() << " " << index.row() << " " << value << " ---- " << role;
qDebug() << roles[Qt::UserRole + 1];
//qDebug() << QSqlTableModel::setData(modelIndex, value);
qDebug() << QSqlQueryModel::setData(index, value);
return false;
}
输出将是:
0 39 QVariant(int, 50) ---- 2
"id"
false
1 39 QVariant(QString, "") ---- 2
"id"
false
2 39 QVariant(QString, "") ---- 2
"id"
false
3 39 QVariant(int, 222) ---- 2
"id"
false
4 39 QVariant(double, 0) ---- 2
"id"
false
5 39 QVariant(int, 0) ---- 2
"id"
false
6 39 QVariant(double, 0) ---- 2
"id"
false
7 39 QVariant(double, 0) ---- 2
"id"
false
确定我的 setData 方法是错误的,但我不明白那里应该发生什么,我没有找到任何例子。
我的假设是否错误,即我需要子类化 QSqlTableModel 以便能够通过 QQmlContext 将模型放入 QML,而不是显示具有像我的列命名一样命名的角色的列?如果不是,我如何将第 1 列的内容放入 QMLTableview:
TableViewColumn {
role: "id" // what should be the role if I don't subclass???
title: "ID"
width: 80
}
我很高兴得到任何帮助、评论、示例、其他帖子或任何让我更进一步的东西......谢谢
我一直在研究一个例子。
一些注意事项:
- QML 项目,例如
TableView
需要一个模型,所以我认为QSqlTableModel
是一个很好的选择。当然,you have other models可以用来处理数据项。 - 在 class
MySqlTableModel
中您将看到所需的角色名称。MySqlTableModel
重新实现roleNames()
以公开角色名称,以便可以通过 QML 访问它们。 - 您可以在
MySqlTableModel
中重新实现setData
方法,但我认为最好使用QSqlTableModel
提供的方法insertRecord
。
我希望这个例子能帮助您改正错误。
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "mysqltablemodel.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydb");
if(!db.open()) {
qDebug() << db.lastError().text();
return 0;
}
QSqlQuery query(db);
if(!query.exec("DROP TABLE IF EXISTS mytable")) {
qDebug() << "create table error: " << query.lastError().text();
return 0;
}
if(!query.exec("CREATE TABLE IF NOT EXISTS mytable \
(id integer primary key autoincrement, name varchar(15), salary integer)")) {
qDebug() << "create table error: " << query.lastError().text();
return 0;
}
MySqlTableModel *model = new MySqlTableModel(0, db);
model->setTable("mytable");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
QSqlRecord rec = model->record();
rec.setValue(1, "peter");
rec.setValue(2, 100);
model->insertRecord(-1, rec);
rec.setValue(1, "luke");
rec.setValue(2, 200);
model->insertRecord(-1, rec);
if(model->submitAll()) {
model->database().commit();
} else {
model->database().rollback();
qDebug() << "database error: " << model->lastError().text();
}
QQmlApplicationEngine engine;
QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("myModel", model);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
mysqltablemodel.h
#ifndef MYSQLTABLEMODEL_H
#define MYSQLTABLEMODEL_H
#include <QSqlTableModel>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlQuery>
#include <QDebug>
class MySqlTableModel : public QSqlTableModel
{
Q_OBJECT
public:
MySqlTableModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
Q_INVOKABLE QVariant data(const QModelIndex &index, int role=Qt::DisplayRole ) const;
Q_INVOKABLE void addItem(const QString &name, const QString &salary);
protected:
QHash<int, QByteArray> roleNames() const;
private:
QHash<int, QByteArray> roles;
};
#endif // MYSQLTABLEMODEL_H
mysqltablemodel.cpp
#include "mysqltablemodel.h"
MySqlTableModel::MySqlTableModel(QObject *parent, QSqlDatabase db): QSqlTableModel(parent, db) {}
QVariant MySqlTableModel::data ( const QModelIndex & index, int role ) const
{
if(index.row() >= rowCount()) {
return QString("");
}
if(role < Qt::UserRole) {
return QSqlQueryModel::data(index, role);
}
else {
return QSqlQueryModel::data(this->index(index.row(), role - Qt::UserRole), Qt::DisplayRole);
}
}
QHash<int, QByteArray> MySqlTableModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Qt::UserRole + 1] = "name";
roles[Qt::UserRole + 2] = "salary";
return roles;
}
void MySqlTableModel::addItem(const QString &name, const QString &salary)
{
QSqlRecord rec = this->record();
rec.setValue(1, name);
rec.setValue(2, salary.toInt());
this->insertRecord(-1, rec);
if(this->submitAll()) {
this->database().commit();
} else {
this->database().rollback();
qDebug() << "database error: " << this->lastError().text();
}
}
main.qml
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
TableView {
id: tableView
anchors.fill: parent
TableViewColumn {
role: "name"
title: "Name"
width: 200
}
TableViewColumn {
role: "salary"
title: "Salary"
width: 200
}
model: myModel
}
Button {
id: addButton
anchors.verticalCenter: parent.verticalCenter
text: "Add item"
onClicked: {
if (nameBox.text || salaryBox.text) {
myModel.addItem(nameBox.text, salaryBox.text)
}
}
}
TextField {
id: nameBox
placeholderText: "name"
anchors.verticalCenter: parent.verticalCenter
anchors.left: addButton.right
anchors.leftMargin: 5
}
TextField {
id: salaryBox
placeholderText: "salary"
anchors.verticalCenter: parent.verticalCenter
anchors.left: nameBox.right
anchors.leftMargin: 5
}
}