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:
...
我已经对 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:
...