子类化 QSqlTableModel 插入新值

Posted

技术标签:

【中文标题】子类化 QSqlTableModel 插入新值【英文标题】:Subclassing QSqlTableModel insert new value 【发布时间】:2017-01-16 21:10:42 【问题描述】:

我想在 QML-Tableview 中显示来自本地 db-File 的 SQL 数据,而不是想对 sql-database 进行一些编辑。 大约三周后我设法做到了:在 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 列。但是我的 sqlDatabase 中不会存储任何内容

我的 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
        

我很高兴得到任何帮助、评论、示例、其他帖子或任何能让我更进一步的东西......谢谢

【问题讨论】:

Here你有一个很好的例子。 不幸的是,这个示例以我能找到的最多的方式结束 -> 显示 SQL 数据。但我正在寻找的是“setData-Method”来编辑或附加数据到 SQL 数据库。 好吧,看来我没有理解正确的一切。我不需要继承 setData。我刚刚写了这个:QSqlRecord record = sqlModel-&gt;record(); record.setValue("id", 87); //qDebug() &lt;&lt; record.fieldName(0) &lt;&lt; " _ " &lt;&lt; record.value(0); qDebug() &lt;&lt; sqlModel-&gt;insertRecord(-1, record); qDebug() &lt;&lt; sqlModel-&gt;submitAll(); 这有时可以完成工作,但有时 submitAll() 返回 false。我不明白为什么它有时会填满一行,有时却没有...... 【参考方案1】:

我一直在研究一个例子。

一些注意事项:

QML 项目如TableView 需要一个模型,所以我认为QSqlTableModel 是一个很好的选择。当然,you have other models 可以用来处理数据项。 在mysqlTableModel 类中,您将看到所需的角色名称。 MySqlTableModel 重新实现 roleNames() 以公开角色名称,以便可以通过 QML 访问它们。 你可以在MySqlTableModel中重新实现setData方法,但是我觉得还是使用QSqlTableModel提供的方法insertRecord比较好。

我希望这个例子能帮助你修正你的错误。

ma​​in.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();
    

ma​​in.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
    

【讨论】:

非常感谢,使用您的提交、提交例程并显示 lastError 让我很快找到了我的问题!我试图只用 id 填充数据库,但其他值是“NULL”,这是我的数据库不允许的。如果我将所有值设置为至少 0,它现在可以正常工作了!正如我所说,谢谢! :) 我很高兴能帮上忙!干得好,编码愉快! :)

以上是关于子类化 QSqlTableModel 插入新值的主要内容,如果未能解决你的问题,请参考以下文章

子类化自定义 UICollectionViewLayout 实现一定的删除和插入效果

没有子类化的 QOpenGLWidget

QT笔记:数据库总结之SQL模型类-QSqlTableModel模型

子类化 uitableview 单元而不使用 uitableviewcontroller

Room - 插入新值后执行删除

链表不插入新值“C语言”