Qt-如何实现一个可读写的QSqlQueryModel?

Qt-How to implement a read-write QSqlQueryModel?

我已经对 QSqlQueryModel::setData() 和 QSqlQueryModel::flags() 进行了子类化和重新实现,现在我可以编辑这个模型了,但是这里会出问题:

我编辑了记录中的第四个字段,但随后,第四个字段和后面的内容都更改为相同的内容:

这是我的 scoremodel.cpp:

#include <QtSql>
#include "scoremodel.h"
#include "mainwindow.h"    //MainWindow::sqlToQueryScore
#include <QDebug>

ScoreModel::ScoreModel(QObject *parent)
    : QSqlQueryModel(parent)
{
}

Qt::ItemFlags ScoreModel::flags(
        const QModelIndex &index) const
{
    Qt::ItemFlags flags = QSqlQueryModel::flags(index);
    if (index.column() != 0 && index.column() != 11)
        flags |= Qt::ItemIsEditable;
    return flags;
}

bool ScoreModel::setData(const QModelIndex &index, const QVariant &value, int /* role */)
{
    if (index.column() == 0 || index.column() == 11)
        return false;

    QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
    int id = data(primaryKeyIndex).toInt();
    qDebug()<<"id:"<<id;
    clear();

    bool ok;
    switch(index.column()){
    case 1:
        ok = setYear(id,value.toString());
    case 2:
        ok = setStudentName(id,value.toString());
    case 3:
        ok = setStudentClass(id,value.toString());
    case 4:
        ok = setTestTime(id,value.toString());
    case 5:
        ok = setTestSubject(id,value.toString());
    case 6:
        ok = setTestType(id,value.toString());
    case 7:
        ok = setTestScore(id,value.toString());
    case 8:
        ok = setStudyPeriod(id,value.toString());
    case 9:
        ok = setTestContent(id,value.toString());
    case 10:
        ok = setTeacherRemark(id,value.toString());
    default:
        ok = false;
    }
    refresh();
    return ok;
}


void ScoreModel::refresh()
{
    qDebug()<<"sqlToQueryScore in refresh:"<<MainWindow::sqlToQueryScore;
    setQuery(MainWindow::sqlToQueryScore);
    setHeaderData(0, Qt::Horizontal, tr("序号"));
    setHeaderData(1, Qt::Horizontal, tr("年份"));
    setHeaderData(2, Qt::Horizontal, tr("学生姓名"));
    setHeaderData(3, Qt::Horizontal, tr("学生班级"));
    setHeaderData(4, Qt::Horizontal, tr("测试时间"));
    setHeaderData(5, Qt::Horizontal, tr("测试科目"));
    setHeaderData(6, Qt::Horizontal, tr("测试类型"));
    setHeaderData(7, Qt::Horizontal, tr("测试成绩"));
    setHeaderData(8, Qt::Horizontal, tr("学习周期"));
    setHeaderData(9, Qt::Horizontal, tr("测试内容"));
    setHeaderData(10, Qt::Horizontal, tr("教师评语"));
    setHeaderData(11, Qt::Horizontal, tr("数据插入时间"));

}

bool ScoreModel::setYear(int id, const QString &year){
    QSqlQuery query;
    query.prepare("update test_score set year = ? where id = ?");
    query.addBindValue(year);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setStudentName(int id, const QString &studentName){
    QSqlQuery query;
    query.prepare("update test_score set student_name = ? where id = ?");
    query.addBindValue(studentName);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setStudentClass(int id,const QString &studentClass){
    QSqlQuery query;
    query.prepare("update test_score set student_class = ? where id = ?");
    query.addBindValue(studentClass);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setTestTime(int id,const QString &testTime){
    QSqlQuery query;
    query.prepare("update test_score set test_time = ? where id = ?");
    query.addBindValue(testTime);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setTestSubject(int id,const QString &testSubject){
    QSqlQuery query;
    query.prepare("update test_score set test_subject = ? where id = ?");
    query.addBindValue(testSubject);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setTestType(int id,const QString &testType){
    QSqlQuery query;
    query.prepare("update test_score set test_type = ? where id = ?");
    query.addBindValue(testType);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setTestScore(int id,const QString &testScore){
    QSqlQuery query;
    query.prepare("update test_score set test_score = ? where id = ?");
    query.addBindValue(testScore);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setStudyPeriod(int id,const QString &studyPeriod){
    QSqlQuery query;
    query.prepare("update test_score set study_period = ? where id = ?");
    query.addBindValue(studyPeriod);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setTestContent(int id,const QString &testContent){
    QSqlQuery query;
    query.prepare("update test_score set test_content = ? where id = ?");
    query.addBindValue(testContent);
    query.addBindValue(id);
    return query.exec();
}
bool ScoreModel::setTeacherRemark(int id,const QString &teacherRemark){
    QSqlQuery query;
    query.prepare("update test_score set teacher_remark = ? where id = ?");
    query.addBindValue(teacherRemark);
    query.addBindValue(id);
    return query.exec();
}

我调试了很久time.And如果你能帮助我,我将不胜感激
谢谢!

除了如下所示实现您想要的解决方案之外,我还尝试减少显示的代码,另一方面,我建议使用 QSqlTableModel.

#include <QApplication>
#include <QMessageBox>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlTableModel>
#include <QTableView>

class SqlQueryModel: public QSqlQueryModel{
public:
    using QSqlQueryModel::QSqlQueryModel;
    Qt::ItemFlags flags(const QModelIndex &index) const {
        return QSqlQueryModel::flags(index) | Qt::ItemIsEditable;
    }
    bool setData(const QModelIndex &index, const QVariant &value, int role){
        if (index.isValid() && role == Qt::EditRole) {
            QSqlQuery qry;
            qry.prepare(QString("update test_score set %1 = ? where id = ?").arg(record().fieldName(index.column())));
            qry.addBindValue(value);
            qry.addBindValue(query().value(record().indexOf("id")));
            if(!qry.exec())
                return false;
            setQuery(query().lastQuery());
            return true;
        }
        return false;
    }
};

static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(":memory:");
    if (!db.open()) {
        QMessageBox::critical(nullptr, QObject::tr("Cannot open database"),
                              QObject::tr("Unable to establish a database connection.\n"
                                          "This example needs SQLite support. Please read "
                                          "the Qt SQL driver documentation for information how "
                                          "to build it.\n\n"
                                          "Click Cancel to exit."), QMessageBox::Cancel);
        return false;
    }

    QSqlQuery query;
    query.exec("create table test_score (id int primary key, student_name varchar(20), student_class varchar(20))");
    query.exec("insert into test_score values(101, 'name1', 'Young')");
    query.exec("insert into test_score values(102, 'name2', 'Holand')");
    query.exec("insert into test_score values(103, 'Lars', 'Gordon')");
    query.exec("insert into test_score values(104, 'Roberto', 'Robitaille')");
    query.exec("insert into test_score values(105, 'Maria', 'Papadopoulos')");
    return true;
}


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    if(!createConnection())
        return -1;
    QTableView view;
    SqlQueryModel model;
    model.setQuery("SELECT * FROM test_score");
    view.setModel(&model);
    view.show();
    return a.exec();
}

仔细查看您的代码,错误是由于每个 case.

中缺少 break 引起的
...
switch(index.column()){
case 1:
    ok = setYear(id,value.toString());
    break; // <---
case 2:
    ok = setStudentName(id,value.toString());
    break; // <---
case 3:
...