如何在QSqlRelationalTableModel中刷新外键下拉列表
解决Qt 6.8.2中QSqlRelationalTableModel关联下拉列表不实时更新的问题
问题场景
基于Qt 6.8.2的SQLite桌面应用中,master表(含id、name字段)与details表(含id、idMaster、value字段)通过QSqlRelationalTableModel建立主从关联,details表的idMaster列通过QSqlRelationalDelegate显示为包含master表名称的下拉框。但增删master表行后,details表的下拉选项无法实时同步,需重启应用才生效,调用modelDetails->select()、setFilter()等方法均无效。
问题原因
QSqlRelationalDelegate使用的关联下拉模型(QSqlRelationModel)采用缓存机制,master表数据变更时,该缓存模型不会自动触发刷新,导致下拉选项停留在旧数据状态。
解决方案
通过监听master表模型的增删改信号,主动刷新details表关联列的下拉模型,实现实时同步。
步骤1:监听master表的变更信号
在初始化modelMaster后,添加信号连接,捕获master表的行插入、删除、数据修改事件:
// 初始化master模型后添加以下代码 connect(modelMaster, &QSqlTableModel::rowsInserted, this, [=]() { refreshDetailsRelationalCombo(); }); connect(modelMaster, &QSqlTableModel::rowsRemoved, this, [=]() { refreshDetailsRelationalCombo(); }); connect(modelMaster, &QSqlTableModel::dataChanged, this, [=]() { refreshDetailsRelationalCombo(); });
步骤2:实现下拉模型刷新函数
在主窗口类中添加成员函数refreshDetailsRelationalCombo,用于刷新details表关联列的下拉选项:
void YourMainWindow::refreshDetailsRelationalCombo() { // 获取details模型中idMaster列对应的关联模型 QSqlRelationModel* relModel = modelDetails->relationModel(static_cast<int>(ColumnsDetails::MODEL_COL_ID_MASTER)); if (relModel) { relModel->select(); // 重新查询master表,更新下拉选项 // 强制视图刷新该列的委托显示 ui->viewDetails->viewport()->update(); } }
关键说明
- 无需重新调用
modelDetails->setRelation(),直接刷新已存在的关联模型更高效; dataChanged信号用于处理master表中name字段修改的场景,保证下拉选项的名称同步更新;viewport()->update()强制视图刷新,确保下拉框立即显示最新选项。
修改后的完整代码片段
QSqlDatabase db = QSqlDatabase::database(DATABASE_NAME); // setup Details model modelDetails = new QSqlRelationalTableModel(this, db); modelDetails->setTable(TABLE_DETAILS); modelDetails->setRelation(static_cast<int>(ColumnsDetails::MODEL_COL_ID_MASTER), QSqlRelation("master", "id", "name")); modelDetails->setEditStrategy(TableModel::OnRowChange); modelDetails->select(); // setup Details QTableView ui->viewDetails->setModel(modelDetails); ui->viewDetails->setItemDelegate(new QSqlRelationalDelegate(ui->viewDetails)); // setup Master model modelMaster = new QSqlRelationalTableModel(this, db); modelMaster->setTable(TABLE_MASTER); modelMaster->setEditStrategy(TableModel::OnRowChange); modelMaster->select(); // setup Master QTableView ui->viewMaster->setModel(modelMaster); ui->viewMaster->setItemDelegate(new QSqlRelationalDelegate(ui->viewMaster)); // 新增:监听master表变更,同步details下拉选项 connect(modelMaster, &QSqlTableModel::rowsInserted, this, [=]() { refreshDetailsRelationalCombo(); }); connect(modelMaster, &QSqlTableModel::rowsRemoved, this, [=]() { refreshDetailsRelationalCombo(); }); connect(modelMaster, &QSqlTableModel::dataChanged, this, [=]() { refreshDetailsRelationalCombo(); }); // when the user selects a Master row, filter the Details table connect(ui->tableMaster->selectionModel(), &QItemSelectionModel::currentRowChanged, this, [=](const QModelIndex ¤t, const QModelIndex &previous) { const QAbstractItemModel *model = current.model(); QModelIndex indexMaster = model->index(current.row(), static_cast<int>(ColumnsMaster::MODEL_COL_ID)); int idMaster = model->data(indexMaster).toInt(); modelDetails->setFilter(QString("idMaster=%1").arg(idMaster)); // 修正原代码笔误:tableDetails改为modelDetails });
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

