C++ Qt开发:SqlRelationalTable关联表组件

Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍SqlRelationalTable关联表组件的常用方法及灵活运用。

在上一篇文章中详细介绍了SqlTableModle组件是如何使用的,本篇文章将介绍SqlRelationalTable关联表组件,该该组件其实是SqlTableModle组件的扩展类,其提供了一个带关系的数据模型,用于处理数据库中的表与表之间的关系。通过这个类,你可以在一个表中使用外键关联到另一个表的数据上。例如将主表中的某个字段与附加表中的特定字段相关联起来,QSqlRelation(关联表名,关联ID,名称)就是用来实现多表之间快速关联的。

1.1 ComboBox

首先我们来实现一个简单的联动效果,数据库组件可以与ComboBox组件形成多级联动效果,在日常开发中多级联动效果应用非常广泛,例如当我们选择指定用户时,让其在另一个ComboBox组件中列举出该用户所维护的主机列表,又或者当用户选择省份时,自动列举出该省份下面的城市列表等。

在进行联动之前需要创建两张表,表结构内容介绍如下:

  • User(id,name)表:存储指定用户的ID号与用户名
  • UserAddressList(id,name,address)表:与User表中的用户名相关联,存储该用户所管理的主机列表信息

通过数据库组件实现的联动非常简单,初始化表结构得到了两张表,当程序运行时默认在MainWindow构造函数处填充第一个ComboBox组件,也就是执行一次数据库查询,并将结果通过addItem()放入到第一个组件内。

QSqlDatabase db;MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);InitMultipleSQL();db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("./database.db");if (!db.open()){std::cout << db.lastError().text().toStdString()<< std::endl;return;}QSqlQuery query;query.exec("select * from User;");QSqlRecord rec = query.record();while(query.next()){int index_name = rec.indexOf("name");QString data_name = query.value(index_name).toString();ui->comboBox_user->addItem(data_name);}
}

而当用户选中了第一个ComboBox组件时,则让其转到槽函数on_comboBox_activated(const QString &arg1)上面,如下图所示;

该槽函数需要一个传入参数,此参数代表组件选中的文本内容,通过利用该文本内容在数据库内执行二次查询并将查询结果填充之对应的第二个ComboBox组件内即可实现组件的联动选择效果,其槽函数代码如下所示;

void MainWindow::on_comboBox_user_activated(const QString &arg1)
{if(db.open()){QSqlQuery query;query.prepare("select * from UserAddressList where name = :x");query.bindValue(":x",arg1);query.exec();QSqlRecord rec = query.record();ui->comboBox_address->clear();while(query.next()){int index = rec.indexOf("address");QString data_ = query.value(index).toString();ui->comboBox_address->addItem(data_);}}
}

读者可自行运行案例中的SqlComboBox案例,运行后可自行选择不同的用户名,则此时会输出该用户名所对应的地址表,如下图所示;

1.2 TableView

接着,我们继续以TableView组件为例,简单介绍一下如何实现组件与数据的绑定,首先我们需要创建一个表并插入几条测试记录,运行如下代码实现建库建表.

创建一张新表,表结构内容介绍如下:

  • LyShark(name,age)表:存储指定用户名与用户年龄

在主构造函数中我们可以直接通过QSqlQueryModel来得到特定表中的记录,并通过setHeaderData将表中的数据关联到对应的数据模型内,最后通过setModel方法即可将对应的表数据关联到前端显示,其核心代码如下所示;

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);Init();QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("./database.db");if (!db.open()){std::cout << db.lastError().text().toStdString()<< std::endl;return;}// 查询数据表中记录qryModel=new QSqlQueryModel(this);qryModel->setQuery("SELECT * FROM LyShark ORDER BY id");if (qryModel->lastError().isValid()){return;}// 设置TableView表头数据qryModel->setHeaderData(0,Qt::Horizontal,"ID");qryModel->setHeaderData(1,Qt::Horizontal,"Name");qryModel->setHeaderData(2,Qt::Horizontal,"Age");// 将数据绑定到模型上theSelection=new QItemSelectionModel(qryModel);ui->tableView->setModel(qryModel);ui->tableView->setSelectionModel(theSelection);ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
}

运行代码后,程序会从数据库内取出结果并输出到tableView组件上,如下图所示;

1.3 SqlRelationalTable

在最开始我们也说过,SqlRelationalTable 并不是Qt中标准的类或方法。它仅仅只是QSqlTableModel的一个子类,其支持在关系数据库表之间建立关系,建立关联时我们只需要使用setRelation方法即可。

setRelationQSqlRelationalTableModel 类中的一个方法,用于设置模型中某一列的关联关系。这个方法的目的是告诉模型某一列的值在另一个表中有关联,并提供相关的信息,以便在视图中显示更有意义的数据而不是外键的原始值。

以下是 setRelation 方法的简单说明:

void QSqlRelationalTableModel::setRelation(int column, const QSqlRelation &relation);
  • column: 要设置关联关系的列的索引。
  • relation: 包含关联信息的 QSqlRelation 对象。

QSqlRelation 的构造函数如下:

QSqlRelation::QSqlRelation(const QString &tableName, const QString &indexColumn, const QString &displayColumn);
  • tableName: 关联的表的名称。
  • indexColumn: 关联表中与当前表关联的列的名称,通常是外键列。
  • displayColumn: 关联表中要显示的列的名称,通常是与外键列相关的实际数据。

示例:

QSqlRelationalTableModel model;
model.setTable("orders");
model.setRelation(2, QSqlRelation("customers", "customer_id", "customer_name"));
model.select();

在这个例子中,第二列(索引为2的列)的数据将从名为 “customers” 的表中获取,该表的外键列为 “customer_id”,并且在视图中显示的是该关联表的 “customer_name” 列的值。使用 setRelation 方法可以使得在表格中更容易地显示和编辑关联数据,而不是直接显示外键的值。

在关联表之前,我们需要设置初始化数据,此处我们提供两个表结构,表Student用于存储学生名字以及学生课程号,另一张Departments则用于存储每个编号所对应的系名称,运行代码完成创建。

// 初始化数据表
void MainWindow::InitSQL()
{QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("./database.db");if (!db.open())return;// 执行SQL创建表db.exec("DROP TABLE Student");db.exec("CREATE TABLE Student (""id INTEGER PRIMARY KEY AUTOINCREMENT, ""name VARCHAR(40) NOT NULL, ""departID INTEGER NOT NULL)");// 逐条插入数据db.exec("INSERT INTO Student(name,departID) VALUES('zhangsan',10)");db.exec("INSERT INTO Student(name,departID) VALUES('lisi',20)");db.exec("INSERT INTO Student(name,departID) VALUES('wangwu',30)");db.exec("INSERT INTO Student(name,departID) VALUES('wangmazi',40)");db.exec("DROP TABLE Departments");db.exec("CREATE TABLE Departments(""departID INTEGER NOT NULL,""department VARCHAR(40) NOT NULL)");db.exec("INSERT INTO Departments(departID,department) VALUES (10,'数学学院')");db.exec("INSERT INTO Departments(departID,department) VALUES (20,'物理学院')");db.exec("INSERT INTO Departments(departID,department) VALUES (30,'计算机学院')");
}

接着我们来看下在MainWindow构造函数中是如何进行初始化和表关联的,以下是对代码的简要说明:

打开数据库连接

创建一个 SQLite 数据库连接,并指定了数据库文件的路径。如果数据库连接成功打开,就继续执行后面的代码。

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("./database.db");
if (!db.open())return;

设置主窗口的布局和属性

将主窗口的中央部件设置为一个 QTableView,同时对表格的选择行为和外观进行了设置。

this->setCentralWidget(ui->tableView);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setAlternatingRowColors(true);

打开数据表并设置模型

创建一个 QSqlRelationalTableModel 并设置了一些表格的属性,包括表名、编辑策略、排序等。

tabModel = new QSqlRelationalTableModel(this, db);
tabModel->setTable("Student");
tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
tabModel->setSort(0, Qt::AscendingOrder);tabModel->setHeaderData(0, Qt::Horizontal, "学号");
tabModel->setHeaderData(1, Qt::Horizontal, "姓名");
tabModel->setHeaderData(2, Qt::Horizontal, "学院");

设置查询关系数据表

设置关系型字段,将 “学院” 列与 “Departments” 表中的 “departID” 列关联起来,并在表格中显示 “department” 列的数据。

tabModel->setRelation(2, QSqlRelation("Departments", "departID", "department"));

设置表格的选择模型和代理

代码设置了表格的选择模型,并为表格设置了一个关系型代理(QSqlRelationalDelegate),以便在表格中显示关联表的数据而不是外键的值。

theSelection = new QItemSelectionModel(tabModel);
ui->tableView->setModel(tabModel);
ui->tableView->setSelectionModel(theSelection);
ui->tableView->setItemDelegate(new QSqlRelationalDelegate(ui->tableView));

选择并显示数据表

最后,通过调用 select 方法来选择和显示数据表的内容。

tabModel->select();

其实代码中最重要的部分就是setRelation,我们只要确保数据库文件正确,并且 Student 表和 Departments 表存在,并且在 Student 表中的 “学院” 列与 Departments 表中的 "departID" 列正确关联即可,其他的就交给组件来处理,如下图所示;

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

想畅游在全球顶级金融学识的海洋——人民大学与加拿大女王大学金融硕士

金融职场的你是否想象过有朝一日能够畅游在全球顶级金融学识的海洋中呢&#xff1f;在那里&#xff0c;你可以尽情探索和领略全球顶尖的金融学识的魅力与深度&#xff0c;与来自世界各地的专业人士共同交流和分享经验。这样的场景让人感到兴奋和向往&#xff0c;准备好了吗&…

Goal-Auxiliary Actor-Critic for 6D Robotic Grasping with Point Clouds

题目&#xff1a;基于点云的 6D 机器人抓取目标-辅助行为-评价 摘要&#xff1a;6D 机 器 人 抓 取超 越 自上 而 下捡 垃 圾桶 场 景是 一 项具 有 挑战 性 的任 务 。 以往基于 6 D 抓 取综 合和 机器 人运 动 规划 的解 决方 案 通常 在开 环设 置下 运 行&#xff0c; 对抓…

轻松实现电脑对iPhone应用管理

目录 摘要 引言 用户登录工具和连接设备 电脑可对手机应用程序批量操作 运行APP和查看APP日志 IPA包安装测试 摘要 本文介绍了如何使用克魔助手工具实现电脑对手机应用的管理操作。通过简单的步骤&#xff0c;用户可以批量操作手机应用、运行应用、查看应用日志以及安装测…

企业如何做好内容?媒介盒子分享

在个性化算法的支持下&#xff0c;企业通过创作优质内容使消费者主动选择企业的时代已经来临&#xff0c;对于中小企业来说&#xff0c;这是能够低成本进行营销的好机会。但是有许多企业对内容的理解依旧是片面的&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;企业如何做…

autosar SJBWY 开发

第一天&#xff1a; 解决tasking 增加任意目录源文件的问题&#xff1b; 展开 Advanced 下面 Browse...选你的源文件目录就好了&#xff1b;

彭涛:2023年终复盘,工作,团队,个人!

眨眼2023即将结束&#xff0c;2024即将开启&#xff0c;每年这个时候&#xff0c;都会简单总结下自己这一年&#xff0c;既是对今年的一个复盘和回顾&#xff0c;也是对新一年的向往和期待。 我的2023年&#xff0c;大概分为 「个人」&#xff0c;「家庭」&#xff0c;「团队」…

第二证券:道指再创历史新高,国际油价大跌超2.5%

当地时间周四&#xff0c;美股收盘涨跌不一&#xff0c;道指再创前史新高&#xff0c;标普500指数进一步迫临前史纪录。到收盘&#xff0c;道指涨53.58点&#xff0c;涨幅为0.14%&#xff0c;报37710.10点&#xff1b;标普500指数涨1.77点&#xff0c;涨幅为0.04%&#xff0c;报…

99. 恢复二叉搜索树

#中序遍历&#xff0c;寻找插值位置并交换 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def recoverTree…

啥是构造器?

当我们new一个对象时就是在引用构造器 构造器又叫做构造函数 构造函数一般分为无参构造函数与有参构造函数 假设我们创建一个pet类&#xff0c;这个类里面就会有一个看不见的自动生成的无参构造函数 如果pet类里没有这个隐形的无参构造&#xff0c;我们new一个对象时就会报错…

ArcGIS高程点生成等高线

基本步骤&#xff1a;数据清洗→创建TIN→TIN转栅格→等值线→平滑线。 1.&#xff08;重要&#xff09;数据清理&#xff1a;删除高程点中的高程异常值数据。 2.创建TIN:系统工具→3D Analyst Tools→数据管理→TIN→创建TIN&#xff08;可直接搜索工具TIN&#xff09;。 单击…

铂炭催化剂,2026年市场预计将以6.5%左右的复合年增长率增长

铂碳催化剂广泛用于各种工业应用&#xff0c;包括化学、制药和汽车领域。在对清洁能源的需求不断增加和环境问题意识不断提高的推动下&#xff0c;铂碳催化剂市场正在稳步增长。本次分析&#xff0c;我们将从全球市场和中国市场分别考察铂碳催化剂市场的发展趋势。 全球市场分析…

OSPF ROUTER-ID-新版(15)

目录 整体拓扑 操作步骤 1.INT 验证Router-ID选举规则 1.1 查看路由器Router-ID 1.2 配置R1地址 1.3 查看R1接口信息 1.4 查看R1Router-ID 1.5 删除接口IP并查看Router-ID 1.6 手工配置Router-ID 2.基本配置 2.1 配置R1的IP 2.2 配置R2的IP 2.3 配置R3的IP 2.4 配…

winserver2008 r2服务器iis配置支持flv,f4v,mp4格式视频

很多政府单位网站一直在使用WIN服务器&#xff0c;大部分网站都使用多年基本使用.NET或者CMS系统建站&#xff0c;系统环境也一直是老版本&#xff0c;今天在维护过程中又出现了新问题&#xff0c;上传的MP4文件不支持网站上播放&#xff0c;顺便也分享下解决过程。当我们架设的…

在VMware安装CentOS 7:详细教程

安装准备工作 本地虚拟机&#xff1a;我这里使用的是VMware Workstation 17 Pro centos7系统ISO镜像&#xff1a;我这里使用的是CentOS-7-x86_64-DVD-2009.iso&#xff0c;具体的下载地址是在阿里云官方镜像站&#xff1a;centos-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿…

Springboot启动流程-持续记录中

注:转载请携带本文链接及公众号信息 公众号&#xff1a;codelike 基于springboot2.6.x 源码 Springboot启动之第一篇 SpringApplication构造器 启动入口方法是new SpringApplication.run(),一切的开始都从这里 这里做了什么呢 分为初始化SpringApplication实体、执行run()…

QLayout布局器QObject子节点遍历

遍历QObject的子节点 #include <QObject> #include <QDebug>void printObjectTree(const QObject *object, int level 0) {if (!object) return;// 创建缩进字符串&#xff0c;用于表示层级QString indent(level * 2, ); // 打印对象的类名和对象名qDebug() <…

使用 pytest 相关特性重构 appium_helloworld

一、前置说明 在 pytest 基础讲解 章节,介绍了 pytest 的特性和基本用法,现在我们可以使用 pytest 的一些机制,来重构 appium_helloworld 。 appium_helloworld 链接: 编写第一个APP自动化脚本 appium_helloworld ,将脚本跑起来 代码目录结构: pytest.ini 设置: [pyt…

基于ssm社区生鲜电商平台论文

目 录 摘 要 I Abstract II 1 绪论 1 1.1研究背景 1 1.2研究现状 1 1.3研究内容 2 2 相关技术简介 3 2.1 B/S结构 3 2.2 MYSQL数据库 3 2.3 Java简介 4 2.4 SSM框架简介 5 3 系统分析 7 3.1 可行性分析 7 3.1.1 技术可行性 7 3.1.2 经济可行性 7 3.1.3 操作可行性 7 3.1.3 法律…

利用太阳能供电的远程视频监控方案设计:智能分析网关V4+4G摄像头鱼塘视频监控

一、行业背景 传统的鱼塘养殖模式由于养殖区域面积大、管理难度高&#xff0c;经常会出现偷钓者、盗窃鱼苗、非法入侵等监管难题&#xff0c;给养殖户带来了不小的经济损失。为了解决这些问题&#xff0c;搭建鱼塘远程监控系统成为了必要之举。通过远程监控系统&#xff0c;管…

Gateway集成方法以及拦截器和过滤器的使用

前提&#xff1a;请先创建好一个SpringBoot项目 1. 引入依赖 SpringCloud 和 alibabaCloud 、 SpringBoot间对版本有强制要求&#xff0c;我使用的springboot是3.0.2的版本。版本对应关系请看&#xff1a;版本说明 alibaba/spring-cloud-alibaba Wiki GitHub <dependency…