QTableView搭配QSqlRelationalTableModel时行消失原因排查
QSqlRelationalTableModel设置OnFieldChange后编辑单元格整行消失的解决方法
当使用QSqlRelationalTableModel并将编辑策略设置为OnFieldChange时,修改单元格值后整行会消失,且无法再修改该行其他单元格。即使尝试添加外键、调整编辑策略,问题依然存在。
编辑前效果:
编辑后效果:
问题根源
- 数据库表缺少主键:
QSqlRelationalTableModel依赖主键唯一标识和追踪数据行,无主键时模型无法在提交修改后匹配原行,导致行从视图中消失。 - 模型初始化顺序错误:先调用
select()再设置关联和编辑策略,会导致模型状态不一致,关联无法正确生效。 - 使用数字常量设置编辑策略:直接用
0代替枚举值,代码可读性差且易出错。
解决方案
1. 修改数据库表结构,添加主键
更新建表语句,为两个表添加主键(仅需执行一次):
import sqlite3 with sqlite3.connect('db.db') as con: cur = con.cursor() # 为tab表添加自增主键id cur.execute('CREATE TABLE IF NOT EXISTS tab (id INTEGER PRIMARY KEY AUTOINCREMENT, "static_col", "relation_col1", "relation_col2")') # 将relation表的rel字段设为主键 cur.execute('CREATE TABLE IF NOT EXISTS relation (rel INTEGER PRIMARY KEY)') cur.execute('INSERT INTO tab(static_col) VALUES ("Lorem"), ("ipsum"), ("dolor"),("sit")') cur.execute('INSERT INTO relation(rel) VALUES (69), (322)')
2. 调整模型初始化顺序并修正配置
修改模型初始化代码,确保先完成配置再加载数据,同时使用枚举值设置编辑策略:
from ui_ui import Ui_Form from PyQt5 import QtWidgets from PyQt5.QtSql import QSqlRelationalTableModel, QSqlDatabase, QSqlRelationalDelegate, QSqlRelation, QSqlTableModel import sys db = QSqlDatabase.addDatabase('QSQLITE') db.setDatabaseName('db.db') db.open() class MainWindow(QtWidgets.QWidget, Ui_Form): def __init__(self): QtWidgets.QWidget.__init__(self) self.setupUi(self) table_model = QSqlRelationalTableModel(db=db) table_model.setTable('tab') # 先设置关联(添加主键后,relation_col1的列索引变为2) table_model.setRelation(2, QSqlRelation('relation', 'rel', 'rel')) # 使用枚举值设置编辑策略,可读性更强 table_model.setEditStrategy(QSqlTableModel.OnFieldChange) # 最后执行select加载数据 table_model.select() self.tableView_1.setModel(table_model) delegate = QSqlRelationalDelegate(self.tableView_1) self.tableView_1.setItemDelegateForColumn(2, delegate) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) main = MainWindow() main.show() sys.exit(app.exec_())
关键说明
- 主键的必要性:SQLite和Qt的SQL模型要求表必须有主键,否则无法正确处理行的修改、删除等操作,尤其是即时提交的编辑策略。
- 初始化顺序:必须先完成模型的所有配置(表、关联、编辑策略),再调用
select(),确保模型加载数据时使用正确的配置。 - 列索引修正:添加主键id后,原
relation_col1的列索引从1变为2,需同步修改关联和代理的列参数。
内容的提问来源于stack exchange,提问作者papadulo
相关产品推荐
相关产品推荐

