QDataWidgetMapper用QSortFilterProxyModel时QComboBox不更新模型
问题场景
使用QTableView绑定QSqlRelationalTableModel,搭配QDataWidgetMapper编辑表格当前活动行数值,核心实现代码如下:
model = QSqlRelationalTableModel(self, self.db) model.setEditStrategy(QSqlTableModel.OnFieldChange) model.setTable(table_name) model.setRelation(i, relation_table, 'id', 'kurz') proxy_model = QSortFilterProxyModel(self) proxy_model.setSourceModel(model) view.setModel(proxy_model) cb.setModel(model.relationModel(i)) cb.setModelColumn(model.relationModel(i).fieldIndex('kurz')) mapper = QDataWidgetMapper(self) mapper.setModel(proxy_model) mapper.setItemDelegate(QSqlRelationalDelegate(self)) mapper.addMapping(cb, i)
异常现象
- 直接将
QSqlRelationalTableModel实例设置为视图模型时,所有功能运行符合预期 - 引入
QSortFilterProxyModel作为视图绑定模型后,仅QComboBox绑定的外键字段存在同步异常:QComboBox可正常加载展示关联表数据,但控件内修改的选中值无法同步更新到视图;QLineEdit、日期选择控件等其他控件绑定的普通字段均能正常同步更新 - 查阅官方文档未找到该问题的相关说明,需确认配置流程是否遗漏必要步骤。
根因分析
原生QSqlRelationalDelegate的提交逻辑仅适配直接绑定QSqlRelationalTableModel的场景:当QDataWidgetMapper绑定的模型是QSortFilterProxyModel时,委托拿到的模型索引属于代理模型层,原生委托没有做代理索引到源关系模型索引的映射,外键字段的特殊提交逻辑无法命中源模型的关联字段配置,最终导致QComboBox的修改无法落库同步;普通字段不需要走外键关联的特殊提交逻辑,因此不受代理层影响。
修复方案
自定义继承QSqlRelationalDelegate的委托类,重写setModelData方法,在提交数据前将代理模型索引映射为源QSqlRelationalTableModel的对应索引,再调用父类的提交逻辑即可:
class MapperRelationalDelegate(QSqlRelationalDelegate): def setModelData(self, editor, model, index): # 映射代理索引到源关系模型索引 source_index = model.mapToSource(index) source_model = model.sourceModel() super().setModelData(editor, source_model, source_index)
将QDataWidgetMapper绑定的委托替换为上述自定义类的实例:
mapper.setItemDelegate(MapperRelationalDelegate(self))
替换后QComboBox的修改即可正常同步到视图与源模型。
内容的提问来源于stack exchange,提问作者Oliver Bienert
相关产品推荐
相关产品推荐

