【Qt之QSqlRelationalTableModel】描述及使用

描述

QSqlRelationalDelegate链接: https://blog.csdn.net/MrHHHHHH/article/details/134690139

QSqlRelationalTableModel类为单个数据库表提供了一个可编辑的数据模型,并支持外键。
QSqlRelationalTableModel的行为类似于QSqlTableModel,但允许将列设置为其他数据库表的外键。

左边的屏幕截图显示了QTableView中一个普通的QSqlTableModel。外键(城市和国家)不能解析为人类可读的值。
右边的屏幕截图显示了一个QSqlRelationalTableModel,外键被解析为人类可读的文本字符串。

下面的代码片段展示了如何建立QSqlRelationalTableModel:在这里插入图片描述

	  model->setTable("employee");model->setRelation(2, QSqlRelation("city", "id", "name"));model->setRelation(3, QSqlRelation("country", "id", "name"));

setRelation()函数调用在两个表之间建立关系。第一个调用指定表employee中的第2列是一个外键,它映射表city的字段id,并且视图应该向用户显示城市的名称字段。第二个调用对列3执行类似的操作。

如果使用读写的QSqlRelationalTableModel,可能希望在视图上使用QSqlRelationalDelegate。与默认委托不同,QSqlRelationalDelegate为作为其他表的外键的字段提供了一个组合框。要使用该类,只需在带有QSqlRelationalDelegate实例的视图上调用QAbstractItemView::setItemDelegate():

	  QTableView *view = new QTableView;view->setModel(model);view->setItemDelegate(new QSqlRelationalDelegate(view));

relationaltablemodel示例演示了如何将QSqlRelationalTableModelQSqlRelationalDelegate结合使用,为表提供外键支持。
在这里插入图片描述
注意:

  • 表必须声明主键。
  • 表的主键可能不包含对另一个表的关系。
  • 如果关系表包含引用引用表中不存在的行的键,则包含无效键的行将不通过模型公开。用户或数据库有责任维护引用完整性。
  • 如果关系的显示列名称也用作关系表中的列名称,或者如果它在多个关系中用作显示列名称,则会被别名。别名是关系的表名、显示列名和一个唯一的id,用下划线连接(例如tablename_columnname_id)。QSqlRecord::fieldName()将返回别名列名。当检测到重复时,所有重复显示列名的出现都会被别名,但不会对主表中的列名进行任何别名操作。别名对QSqlRelation没有影响,因此QSqlRelation::displayColumn()将返回原始显示列名。
  • 参考表名称被别名。别名是单词"relTblAl"和关联的列索引用下划线连接(例如,relTblAl_2)。别名可用于过滤表(例如,setFilter("relTblAl_2='Oslo' OR relTblAl_3='USA'"))。
  • 使用setData()时,角色应始终为Qt::EditRole,使用data()时,角色应始终为Qt::DisplayRole

常用方法

  1. 枚举:enum JoinMode
常量描述解释
QSqlRelationalTableModel::InnerJoin0- Inner join mode, return rows when there is at least one match in both tables.— 内部连接模式,当两个表中至少有一个匹配时返回行。
QSqlRelationalTableModel::InnerJoin1- Left join mode, returns all rows from the left table (table_name1), even if there are no matches in the right table (table_name2).— 左连接模式,返回左表(table_name1)中的所有行,即使右表(table_name2)中没有匹配。
  1. void setJoinMode(QSqlRelationalTableModel::JoinMode joinMode)

设置SQL joinMode以显示或隐藏外键为NULL的行。在InnerJoin模式(默认)中,这些行将不会显示:如果想显示它们,请使用LeftJoin模式。

  1. QSqlRelation relation(int column) const

返回列的关系,如果没有设置关系,则返回无效关系。

  1. QSqlTableModel* relationModel(int column) const

返回一个QSqlTableModel对象,用于访问列为外键的表,如果给定列没有关系,则返回0。
返回的对象归QSqlRelationalTableModel所有。

  1. void setRelation(int column, const QSqlRelation &relation)

让指定的列是由关系指定的外索引。
Ex:

    model->setTable("employee");model->setRelation(2, QSqlRelation("city", "id", "name"));

setRelation()调用指定employee表中的第2列是一个外键,它映射表city的字段id,并且视图应该向用户显示城市的名称字段。
注意:表的主键不能包含与另一个表的关系。

  1. void clear()

重新实现QSqlQueryModel::clear()方法。用于清除模型数据。

  1. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const

为索引引用的项返回存储在给定角色下的数据。
注意:如果没有要返回的值,则返回无效的QVariant,而不是返回0`。

  1. bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())

在支持此功能的模型上,从模型中删除从parent下给定列开始的计数列。
如果列已成功删除,则返回true;否则返回false。
基类实现不做任何事情并返回false。
如果实现了自己的模型,如果希望支持删除,则可以重新实现此函数。或者,可以提供自己的API来修改数据。

  1. bool select()

使用通过setTable()设置的表中的数据填充模型,使用指定的筛选和排序条件,如果成功则返回true;否则返回false。
注意:调用select()将恢复所有未提交的更改并删除所有插入的列。

  1. bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

QAbstractItemModel::setData()重新实现。
将具有指定索引的项中角色的数据设置为给定的值。根据编辑策略的不同,值可以立即应用于数据库,也可以缓存在模型中。
如果值可以设置,则返回true,如果出现错误(例如,如果索引超出边界)则返回false。
对于关系列,value必须是索引,而不是显示值。索引也必须存在于被引用的表中,否则函数返回false。

示例

.pro中添加QT += sql
包含头文件

#include <QtWidgets>
#include <QtSql>#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
  1. // 创建表及插入数据
static bool createConnection()
{QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");// 创建在内存中db.setDatabaseName(":memory:");if (!db.open()) {QMessageBox::critical(0, qApp->tr("Cannot open database"),qApp->tr("Unable to establish a database connection.\n""This example needs SQLite support. Please read ""the Qt SQL driver documentation for information how ""to build it.\n\n""Click Cancel to exit."), QMessageBox::Cancel);return false;}// 使用SqlQuery进行表创建及数据添加QSqlQuery query;query.exec("create table person (id int primary key, ""firstname text, lastname int)");query.exec("insert into person values(0, '0', 0)");query.exec("insert into person values(1, '1', 1)");query.exec("insert into person values(4, '2', 2)");query.exec("insert into person values(3, '3', 3)");query.exec("create table itemF (id int primary key,""firstName varchar(20))");query.exec("insert into itemF ""values(0, '小明')");query.exec("insert into itemF ""values(2, '小华')");query.exec("insert into itemF ""values(3, '小芳')");query.exec("insert into itemF ""values(1, '小诸葛')");query.exec("create table itemL (id int, lastName varchar(20))");query.exec("insert into itemL values(0, '赵')");query.exec("insert into itemL values(1, '钱')");query.exec("insert into itemL values(2, '孙')");query.exec("insert into itemL values(3, '李')");return true;
}
  1. // 初始化模型
void initializeModel(QSqlRelationalTableModel *model)
{// 设置表名model->setTable("person");// 手动提交model->setEditStrategy(QSqlTableModel::OnManualSubmit);// 设置外键model->setRelation(1, QSqlRelation("itemF", "id", "firstName"));model->setRelation(2, QSqlRelation("itemL", "id", "lastName"));// 添加表头model->setHeaderData(0, Qt::Horizontal, QObject::tr("id"));model->setHeaderData(1, Qt::Horizontal, QObject::tr("firstName"));model->setHeaderData(2, Qt::Horizontal, QObject::tr("lastName"));// 刷新model->select();
}

上述代码:

  • 创建了一个名为 person 的表,并添加了一些数据。
  • 创建了两个名为 itemFitemL 的表,并添加了一些具有 idfirstNamelastName 属性的数据
  • 这些表和数据将用于后面的 QSqlRelationalTableModel 示例
  • 最后,该函数返回 true
  1. // 创建视图
QTableView *createView(const QString &title, QSqlTableModel *model)
{QTableView *view = new QTableView;// 设置模型view->setModel(model);// 设置委托,这样可以下拉框显示view->setItemDelegate(new QSqlRelationalDelegate(view));view->setWindowTitle(title);return view;
}

上述代码:

  • 定义了一个名为 createView 的函数,函数用于创建一个新的 QTableView
  • 函数使用一个标题和一个 QSqlTableModel 对象作为参数,并使用传入的 QSqlTableModel 对象设置 view 的模型。
  • 使用 QSqlRelationalDelegate 设置 view 的委托,以便在需要显示下拉列表时使用。
  • 最后,函数设置 view 的窗口标题,并将 view 返回给调用者。
  1. // 调用
int main(int argc, char *argv[])
{QApplication app(argc, argv);if (!createConnection())return 1;QSqlRelationalTableModel model;initializeModel(&model);QTableView *view = createView(QObject::tr("Relational Table Model"), &model);view->show();return app.exec();
}

结果

在这里插入图片描述

注意

  • 表必须声明主键
  • 使用setRelation()方法时,关联的表和外键需存在,不然,错误的行不会加载到模型中,不会在视图中显示
  • 使用setItemDelegate(new QSqlRelationalDelegate(view))时,可以将单元格以下拉框方式显示

结论

重剑无锋,大巧不工

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/183723.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java系列-new Object的过程

从《深入理解Java虚拟机》里面的第七章看到了一些&#xff0c;先简单记录一下&#xff0c;好多不懂的。 类从被加载到虚拟机内存中开始&#xff0c;到卸载出内存为止&#xff0c;它的整个生命周期包括&#xff1a;加载、验证、准备、解析、初始化、使用和卸载7个阶段。其中验证…

【海思SS528 | VDEC】MPP媒体处理软件V5.0 | 视频解码模块——学习笔记

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

Retrofit+OkHttp打印Request 请求地址参数

在移动端开发时&#xff0c;我们常常需要像web端一样可以方便地查看我们向服务器发送请求的报文详细日志&#xff08;如请求地址&#xff0c;请求参数&#xff0c;请求类型&#xff0c;服务器响应的耗时时间&#xff0c;请求返回的结果等等&#xff09;。 使用Retrofit时&…

CSS3样式详解之圆角、阴影及变形

目录 前言一、圆角样式&#xff08;border-radius&#xff09;二、元素阴影&#xff08;box-shadow&#xff09;三、过渡动画样式&#xff08;transition&#xff09;1. transition-property(用于设置属性名称)2. transition-duration&#xff08;设置时间&#xff09;3. trans…

【web安全】CSRF漏洞攻击与防御

前言 总结&#xff0c;仅供学习。 csrf的理解 我们了解一个网站有修改信息&#xff0c;密码&#xff0c;添加删除管理&#xff0c;支付转账的功能之后。 通过抓包抓取对方修改操作的数据包样式&#xff0c; 然后在自己网站搭建一个指令。 当别人来访时&#xff0c; 如果…

linux用户管理_用户和组

2 用户管理 2.1 用户和组的基本概念和作用 2.1.1 账户实质 账户实质就是一个用户在系统上的标识&#xff0c;系统依据账户ID来区分每个用户的文件、进程、任务&#xff0c;给每个用户提供特定的工作关键&#xff08;如用户的工作目录、SHELL版本以及环境配置等&#xff09;&…

字符串函数精讲1

又是好几天没有更新了&#xff0c;最近有些忙&#xff0c;但这并不是理由&#xff0c;还是怪我自己玩的时间多了&#xff01;但还是有在每天敲代码的&#xff01;话不多说&#xff0c;开始这一期的学习&#xff1a; strlen的使用和模拟实现 • 字符串以 \0 作为结束标志&#…

前端:实现二级菜单(二级菜单悬浮在一级菜单左侧)

效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…

每日一题:LeetCode-283. 移动零

每日一题系列&#xff08;day 08&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

聚观早报 |亚马逊AWS发布新AI芯片;拼多多Q3营收增长94%

【聚观365】11月30日消息 亚马逊AWS发布新AI芯片 拼多多Q3营收增长94% Redmi K70全新国风配色揭晓 英伟达扩大自动驾驶中国团队 华为nova 12参数细节曝光 亚马逊AWS发布新AI芯片 在美国时间周二举办的Reinvent大会上&#xff0c;亚马逊旗下的云计算部门AWS发布了新的人工…

Docker—更新应用程序

在本部分中&#xff0c;你将更新应用程序和映像。您还将了解如何停止和移除容器。 一、更新源代码 在以下步骤中&#xff0c;当您没有任何待办事项列表项时&#xff0c;您将把“空文本”更改为“您还没有待办事项&#xff01;在上面添加一个&#xff01;” 1、在src/static/…

C#,数值计算——插值和外推,径向基函数插值(RBF_multiquadric)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class RBF_multiquadric : RBF_fn { private double r02 { get; set; } public RBF_multiquadric(double scale 1.0) { this.r02 Globals.SQR(scale); } publi…

智能客服核心技术——预测会话与答案生成

1.信息检索 2. 句型模板匹配标准问题生成答案 3.根据知识图谱推理得到答案

vue发送请求携带token,拼接url地址下载文件

封装请求 &#xff0c;该请求为普通的get请求 该请求返回值为&#xff1a; 请求成功之后拼接URL地址下载文件 代码块 downTemplateRequest(activeKeys.value).then((res) > {let url http://47.169.168.99:18888/media/${res.data.name};var elink document.createElemen…

ApiSix的docker 容器化部署及使用

⼀&#xff0e;etcd安装 Docekr安装Etcd 环境准备 此处安装&#xff0c;是利⽤下载的 etcd 源⽂件&#xff0c;利⽤ docker build 构建完整镜像&#xff0c;具体操作如下&#xff1a; 1.环境准备 1.1. 新建⽂件夹 在磁盘某个路径下新建⼀个⽂件夹&#xff0c;⽤处操作 Dockerfi…

Linux系统平均负载

我们经常会使用 top 命令来查看系统的性能情况&#xff0c;在 top 命令的第一行可以看到 load average 这个数据&#xff0c;如下图所示&#xff1a; load average 包含 3 列&#xff0c;分别表示 1 分钟、5 分钟和 15 分钟的 系统平均负载 系统平均负载&#xff1a; 如果将 …

golang—kafka架构原理快速入门以及自测环境搭建(docker单节点部署)

kafka Apache Kafka 是一个分布式的流处理平台。它具有以下特点&#xff1a; 支持消息的发布和订阅&#xff0c;类似于 RabbtMQ、ActiveMQ 等消息队列支持数据实时处理能保证消息的可靠性投递支持消息的持久化存储&#xff0c;并通过多副本分布式的存储方案来保证消息的容错高…

Java中xml映射文件是干什么的

Java中的XML映射文件主要用于将Java对象与XML文档之间进行转换。它通常用于处理数据交换和存储&#xff0c;例如将Java对象转换为XML格式以便在网络上传输或保存到文件中&#xff0c;或者将XML文档解析为Java对象以进行处理。这种转换可以通过Java的JAXB&#xff08;Java Archi…

springMVC实验(二)—调式工具APIFOX的使用

【知识要点】 后端开发调试工具 前后端分离已经成为互联网类软件开发主流模式&#xff0c;没有前端操作的支持&#xff0c;如何调试后端程序的就是开发人员必须解决的问题。如&#xff1a;get类请求可以直接使用浏览器就能模拟测试&#xff0c;但是post、put等类型的请求&…

Ubuntu 环境下 NFS 服务安装及配置使用

需求&#xff1a;公司内部有多台物理服务器&#xff0c;需要A服务器上的文件让B服务器访问&#xff0c;也就是两台服务器共享文件&#xff0c;当然也可以对A服务器上的文件做权限管理&#xff0c;让B服务器只读或者可读可写 1、NFS 介绍 NFS 是 Network FileSystem 的缩写&…