【Qt之QSqlRelationalDelegate】描述及使用

描述

QSqlRelationalDelegate类提供了一个委托,用于显示和编辑来自QSqlRelationalTableModel的数据。

与默认委托不同,QSqlRelationalDelegate为作为其他表的外键的字段提供了一个组合框。

要使用该类,只需在带有QSqlRelationalDelegate实例的视图上调用QAbstractItemView::setItemDelegate();

Ex:

cpp 复制代码
    QSqlRelationalTableModel* pModel = new QSqlRelationalTableModel();
    pModel->setTable("person");
    pModel->setRelation(2, QSqlRelation("items", "id", "itemtype"));

    ui->tableView->setModel(pModel);
    ui->tableView->setItemDelegate(new QSqlRelationalDelegate());
    pModel->select();

关系表模型示例(如下所示)演示了如何将QSqlRelationalDelegateQSqlRelationalTableModel结合使用,为表提供外键支持。

重写

有两个重写方法:

  1. QWidget *QSqlRelationalDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
  2. void QSqlRelationalDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
createEditor
cpp 复制代码
QWidget *createEditor(QWidget *aParent,
                      const QStyleOptionViewItem &option,
                      const QModelIndex &index) const
{
    const QSqlRelationalTableModel *sqlModel = qobject_cast<const QSqlRelationalTableModel *>(index.model());
    QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0;
    if (!childModel)
        return QItemDelegate::createEditor(aParent, option, index);

    QComboBox *combo = new QComboBox(aParent);
    combo->setModel(childModel);
    combo->setModelColumn(childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn()));
    combo->installEventFilter(const_cast<QSqlRelationalDelegate *>(this));

    return combo;
}
  • 上述代码实现了自定义委托的createEditor函数,用于创建一个QComboBox作为单元格的编辑器
  • 通过index.model()获取主数据模型,并将其qobject_cast转换为QSqlRelationalTableModel类型(如果成功转换,则说明该数据模型具有关联模型)
  • 使用sqlModel->relationModel(index.column())获取与该列关联的子数据模型。如果该列没有关联模型,它将返回0,这意味着将使用默认的委托(QItemDelegate)来创建单元格编辑器。

如果存在关联模型,则创建一个QComboBox,并将其设置为该列的单元格编辑器。

  • 子模型是通过combo->setModel(childModel)设置的,其中childModel是通过sqlModel->relationModel(index.column())获取的
  • 使用sqlModel->relation(index.column()).displayColumn()获取子模型中用于显示选择项的列,并将其设置为QComboBox的模型列,即combo->setModelColumn
  • ComboBox安装一个事件过滤器,使得在编辑完成后能够正确更新主数据模型
  • 最后,返回ComboBox作为单元格编辑器。
setModelData
cpp 复制代码
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    if (!index.isValid())
        return;

    QSqlRelationalTableModel *sqlModel = qobject_cast<QSqlRelationalTableModel *>(model);
    QSqlTableModel *childModel = sqlModel ? sqlModel->relationModel(index.column()) : 0;
    QComboBox *combo = qobject_cast<QComboBox *>(editor);
    if (!sqlModel || !childModel || !combo) {
        QItemDelegate::setModelData(editor, model, index);
        return;
    }

    int currentItem = combo->currentIndex();
    int childColIndex = childModel->fieldIndex(sqlModel->relation(index.column()).displayColumn());
    int childEditIndex = childModel->fieldIndex(sqlModel->relation(index.column()).indexColumn());
    sqlModel->setData(index,
            childModel->data(childModel->index(currentItem, childColIndex), Qt::DisplayRole),
            Qt::DisplayRole);
    sqlModel->setData(index,
            childModel->data(childModel->index(currentItem, childEditIndex), Qt::EditRole),
            Qt::EditRole);
}
  • 上述代码实现了自定义委托的setModelData函数,用于将编辑器中的数据更新到主数据模型中
  • 首先,检查index是否有效,如果无效,则直接返回
  • 通过qobject_cast将数据模型转换为QSqlRelationalTableModel类型,并使用index.column()获取正在编辑的列的索引
  • 通过sqlModel->relationModel(index.column())获取与该列关联的子数据模型,如果该列没有关联模型,则将其设置为0
  • 通过qobject_cast将编辑器转换为QComboBox类型,并检查它们是否存在。如果不存在,则说明该列没有关联子模型或者使用默认委托编辑器,就调用默认委托的setModelData函数来更新数据模型,然后返回。

如果存在关联子模型和ComboBox编辑器,它就使用combo->currentIndex()获取当前ComboBox选中项的索引,使用sqlModel->setData将选中项的值设置到主数据模型的index位置。这里使用了两次sqlModel->setData,分别将选中项的"显示值"和"编辑值"设置到主数据模型中,其中"显示值"是通过sqlModel->relation(index.column()).displayColumn()获取的子模型中的列数据,而"编辑值"是通过sqlModel->relation(index.column()).indexColumn()获取的子模型中指定的列数据

  • 最后,完成了所有数据更新操作

注意

如果需要下拉框功能,就直接用就行。

先进行自定义信号发送,则需要子类化操作。

结论

记住,你是最好的!如果有人比你好,那就假装没看见他们

相关推荐
辞旧 lekkk5 小时前
【Qt】信号和槽
linux·开发语言·数据库·qt·学习·mysql·萌新
2zcode5 小时前
运动模糊图像复原的MATLAB仿真与优化
开发语言·matlab
袁雅倩19976 小时前
当吸尘器、筋膜枪都用上Type-C,供电方案该怎么选?浅谈PD取电芯片ECP5702的应用
c语言·开发语言·支持向量机·动态规划·推荐算法·最小二乘法·图搜索算法
Aaswk6 小时前
Java Lambda 表达式与流处理
java·开发语言·python
万邦科技Lafite7 小时前
京东item_get接口实战案例:实时商品价格监控全流程解析
java·开发语言·数据库·python·开放api·淘宝开放平台
liuhuizuikeai8 小时前
可视化门禁---Linux/Qt+SqLite篇
linux·运维·qt
Cyber4K8 小时前
【Python专项】进阶语法-系统资源监控与数据采集(1)
开发语言·python·php
Le_ee8 小时前
ctfweb:php/php短标签/.haccess+图片马/XXE
开发语言·前端·php
yong99909 小时前
MATLAB读取高光谱图像
开发语言·matlab
2zcode9 小时前
基于MATLAB的肝病风险评估与分期分析系统设计与实现
开发语言·matlab