Qt主从关系表场景下,如何正确提交新记录?
Qt主从表添加行后视图显示异常问题解决
问题现象
使用QSqlRelationalTableModel实现主从表(programs为主表,timelines为详情表),选中主表行时详情表能正确过滤显示对应数据。但通过按钮添加详情表新行并提交后,记录已写入数据库,QTableView却显示带感叹号的空行,视图失去响应;切换主表行再切回后,该行显示恢复正常。
表结构
programs表
.schema programs CREATE TABLE programs (id INT NOT NULL, duration INT NOT NULL, idSong INT NOT NULL, name TEXT, PRIMARY KEY (id), FOREIGN KEY (idSong) REFERENCES songs(id));
timelines表
.schema timelines CREATE TABLE timelines (idProgram INT NOT NULL, time INT NOT NULL, idBouquet TEXT, idFanSpeed INT NOT NULL, ton INT NOT NULL, PRIMARY KEY (idProgram, time), FOREIGN KEY (idProgram) REFERENCES programs(id), FOREIGN KEY (idBouquet) REFERENCES bouquets(name), FOREIGN KEY (idFanSpeed) REFERENCES fanSpeeds(id));
现有核心代码
模型初始化
QSqlDatabase db = QSqlDatabase::database(DATABASE_NAME); // 主表模型 _modelPrograms = new QSqlRelationalTableModel(this, db); _modelPrograms->setTable("programs"); _modelPrograms->setEditStrategy(QSqlRelationalTableModel::OnRowChange); _modelPrograms->setRelation(static_cast<int>(ColumnsProgram::MODEL_COL_ID_SONG), QSqlRelation("songs", "id", "name")); _modelPrograms->select(); ui->viewPrograms->setModel(_modelPrograms); // 原代码笔误:_model应为_modelPrograms // 详情表模型 _modelTimelines = new QSqlRelationalTableModel(this, db); _modelTimelines->setTable("timelines"); _modelTimelines->setEditStrategy(QSqlRelationalTableModel::OnRowChange); _modelTimelines->setRelation(static_cast<int>(ColumnsTimeline::MODEL_COL_ID_PROGRAM), QSqlRelation("programs", "id", "name")); _modelTimelines->setRelation(static_cast<int>(ColumnsTimeline::MODEL_COL_ID_HUE_MODE), QSqlRelation("hueModes", "id", "name")); // 原代码笔误:少了-> _modelTimelines->setRelation(static_cast<int>(ColumnsTimeline::MODEL_COL_ID_FAN_SPEED), QSqlRelation("fanSpeeds", "name", "name")); // 原代码笔误:少了-> _modelTimelines->select(); ui->viewTimelines->setModel(_modelTimelines); // 原代码笔误:_model应为_modelTimelines
主从行同步
connect(ui->tablePrograms->selectionModel(), &QItemSelectionModel::currentRowChanged, this, [=](const QModelIndex ¤t, const QModelIndex &previous) { const QAbstractItemModel *model = current.model(); QModelIndex indexProgram = model->index(current.row(), static_cast<int>(ColumnsProgram::MODEL_COL_ID)); int idProgram = model->data(indexProgram).toInt(); _modelTimelines->setFilter(QString("idProgram=%1").arg(idProgram)); });
添加新行代码
_modelTimelines->insertRow(_modelTimelines->rowCount()); QModelIndex index = _modelTimelines->index(_modelTimelines->rowCount() - 1, 0); ui->viewTimelines->setCurrentIndex(index); ui->viewTimelines->edit(index);
问题原因
- 关联字段未预设置:添加新行时未主动设置
idProgram字段值,手动填写后模型关联关系未及时加载对应数据,导致视图渲染异常。 - 模型未主动刷新:提交后模型未重新执行查询,无法同步数据库中已写入的完整关联数据;切换主表行时触发
setFilter和隐式select,才完成数据同步。 - 原代码笔误:模型初始化中存在
->遗漏、模型对象赋值错误,可能导致模型状态异常。
解决方案
1. 修正代码笔误
先修复模型初始化中的笔误(如_modelTimelines.setRelation改为_modelTimelines->setRelation,视图绑定正确的模型对象),排除基础错误。
2. 添加新行时预设置关联字段
插入新行时,直接将当前选中的主表idProgram赋值给新行,避免手动填写的延迟或错误:
// 提前在currentRowChanged信号中保存当前选中的主表ID为成员变量_currentProgramId _modelTimelines->insertRow(_modelTimelines->rowCount()); // 给新行设置idProgram字段 QModelIndex progIdIndex = _modelTimelines->index(_modelTimelines->rowCount() - 1, static_cast<int>(ColumnsTimeline::MODEL_COL_ID_PROGRAM)); _modelTimelines->setData(progIdIndex, _currentProgramId); // 切换到需要编辑的列(比如time列) QModelIndex editIndex = _modelTimelines->index(_modelTimelines->rowCount() - 1, static_cast<int>(ColumnsTimeline::MODEL_COL_TIME)); ui->viewTimelines->setCurrentIndex(editIndex); ui->viewTimelines->edit(editIndex);
3. 提交后主动刷新模型
监听模型的submit信号,提交完成后调用select()刷新模型,确保视图获取最新数据:
connect(_modelTimelines, &QSqlRelationalTableModel::submit, this, [=](){ _modelTimelines->select(); });
4. 优化过滤逻辑
在currentRowChanged中设置过滤后,主动调用select()确保模型重新加载数据:
connect(ui->tablePrograms->selectionModel(), &QItemSelectionModel::currentRowChanged, this, [=](const QModelIndex ¤t, const QModelIndex &previous) { const QAbstractItemModel *model = current.model(); QModelIndex indexProgram = model->index(current.row(), static_cast<int>(ColumnsProgram::MODEL_COL_ID)); int idProgram = model->data(indexProgram).toInt(); _modelTimelines->setFilter(QString("idProgram=%1").arg(idProgram)); _modelTimelines->select(); // 主动刷新模型 });
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

