当前位置: 首页 > news >正文

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" 列正确关联即可,其他的就交给组件来处理,如下图所示;

相关文章:

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

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

【LeetCode】修炼之路-0001-Two Sum(两数之和)【python】【简单】

前言 计算机科学作为一门实践性极强的学科,代码能力的培养尤为重要。当前网络上有非常多优秀的前辈分享了LeetCode的最佳算法题解,这对于我们这些初学者来说提供了莫大的帮助,但对于我这种缺乏编程直觉的学习者而言,这往往难以消化吸收。&#xff08;为什么别人就能想出这么优雅…...

秋招复习篇之代码规范

目录 前言 1、变量命名 2、代码空格 1&#xff09;操作符左右一定有空格&#xff0c; 2&#xff09;分隔符&#xff08;, 和;&#xff09;前一位没有空格&#xff0c;后一位保持空格&#xff0c;例如&#xff1a; 3&#xff09;大括号和函数保持同一行&#xff0c;并有一个空格…...

Docker:登录私有仓库\退出私有仓库

一、登录仓库 docker login : 登录到一个Docker镜像仓库&#xff0c;如果未指定镜像仓库地址&#xff0c;默认为官方仓库 Docker Hub 语法: docker login [OPTIONS] [SERVER] docker login -u 用户名 -p 密码 仓库名称 # 登入私有仓库 [rootlocalhost ~]# docker login --…...

与擎创科技共建一体化“数智”运维体系,实现数字化转型

小窗滴滴小编获取最新版公司简介 前言&#xff1a; 哈喽大家好&#xff0c;最近分享的互联网IT热讯大家都挺喜欢&#xff0c;小编看着数据着实开心&#xff0c;感谢大家支持&#xff0c;小编会继续给大家推送。 新岁即将启封&#xff0c;我们一年一期的运维干货年末大讲也要…...

开放网络+私有云=?星融元的私有云承载网络解决方案实例

在全世界范围内的云服务市场上&#xff0c;开放网络一直是一个备受关注的话题。相比于传统供应商的网络设备&#xff0c;开放网络具备软硬件解耦、云原生、可选组件丰富等优势&#xff0c;对云服务商和超大型企业有足够的吸引力。 SONiC作为开源的网络操作系统&#xff0c;使得…...

【Linux学习笔记】Linux下nginx环境搭建

1、下载nginx 安装rpm命令: rpm ivh nginx-release.rpm。(直接使用linux命令下载wget http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm 2、设置nginx开机启动 chkconfig nginx on 3、开启nginx服务 方法一&#xff1a;service nginx…...

Python打包

将 Python 脚本打包成可执行的 .exe 文件,通常可以使用 PyInstaller 这个库来实现。PyInstaller 是一个流行的工具,它可以将 Python 程序和所有相关的依赖打包成一个独立的可执行文件,适用于 Windows、Linux 和 macOS 系统。安装 PyInstaller 首先,需要安装 PyInstaller。…...

2023启示录丨自动驾驶这一年

图片&#xff5c;《老人与海》插图 过去的20年&#xff0c;都没有2023年如此动荡。 大模型犹如一颗原子弹投入科技圈&#xff0c;卷起万里尘沙&#xff0c;传统模式瞬间被夷为平地&#xff0c;在耀眼的白光和巨大的轰鸣声之下&#xff0c;大公司、创业者、投资人甚至是每一位观…...

node实现对git仓库的管理

一、项目背景 一份代码&#xff0c;发布多个小程序。想让技术支持部通过脚本自己获取代码&#xff0c;并通过脚本自动提交到客户的小程序后台。他们自行发布。 现已注册第三方平台&#xff0c;开发人员通过“开发小程序”上传模板。开发人员把代码上传到模板&#xff0c;支持…...

『JavaScript』全面解析JavaScript中的防抖与节流技术及其应用场景

&#x1f4e3;读完这篇文章里你能收获到 理解防抖&#xff08;Debouncing&#xff09;和节流&#xff08;Throttling&#xff09;的概念&#xff1a;了解这两种性能优化技术如何帮助我们更有效地处理频繁触发的事件掌握防抖与节流的实现方法&#xff1a;学习如何在JavaScript中…...

智能优化算法应用:基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.袋獾算法4.实验参数设定5.算法结果6.参考文献7.MA…...

Ubuntu20.04-查看GPU的使用情况及输出详解

1. 查看GPU的使用情况 1.1 nvidia-smi # 直接在终端得到显卡的使用情况 # 不会自动刷新 nvidia-smi# 重定向到文件中 nvidia-smi > nvidia_smi_output.txt# 如果输出的内容部分是以省略号表示的&#xff0c;可以-q nvidia-smi -q 1.2 nvidia-smi -l # 会自动刷新&#x…...

Python中的数据序列

Python中的数据序列 一、作业回顾 1、求幸运数字6 幸运数字6(只要是6的倍数):输入任意数字,如数字8,生成nums列表,元素值为1~8,从中选取幸运数字移动到新列表lucky,打印nums与lucky。 # 第一步:定义二个空列表 nums = [] lucky = [] # 第二步:提示用户输入数字 n…...

带您了解目前AI在测试领域能够解决的那些问题

AI在测试领域主要应用场景 话不多说&#xff0c;直接给结论&#xff1a; 接口测试脚本的自动生成和校验&#xff08;依赖研发ai工具&#xff09;测试用例的自动生成UI自动化测试脚本的自动生成和校验测试文档的自动生成快速了解初涉的业务领域 关于ai对研发和测试的整体影响…...

Jmeter学习总结(2)——时间参数化time

13位的时间戳精确都毫秒级别。 常用的时间定义格式如下&#xff1a; log.info("${__time(,ts)}"); log.info("${ts}"); log.info(vars.get("ts")); //136232232232log.info("${__time(yyyy-MM-dd,)}"); //当前年月日2023-12-2…...

Leetcode 746 使用最小花费爬楼梯

题意理解&#xff1a; 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。 一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯 目标&#xff1a;使用最小的花…...

2023/12/21作业

思维导图 代码 .text .global _start _start: 灯1 gpio时钟使能 [4]->1 0x5000A28 LDR R0,0x50000A28 指定寄存器地址 LDR R1,[R0]将寄存器取出放到R1 ORR R1,R1,#(0x1<<4)将第四位设置为1 STR R1,[R0]读取R0寄存器到R1 PE…...

Python 数据类型 (2)

1 集合类型&#xff1a;一维数组的集合 List列表是一个有序且可变的集合。允许重复成员。 turple元组是一个有序且不可更改的集合。允许重复成员。 Set集合是一个无序且无索引的集合。没有重复的成员。 dict字典是一个有序*且可变的集合。没有重复的成员。 &#xff01;&#x…...

【教程】自动检测和安装Python脚本依赖的第三方库

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 对于新python环境&#xff0c;要运行某个脚本&#xff0c;可能需要安装很多库&#xff0c;一般可以通过提供的requirements.txt来自动安装。但如果没有这个txt&#xff0c;那就得手动一个一个安装&#…...

搞定气象数据的基础统计与可视化

是不是看着一堆气象原始数据就头大&#xff1f; 不会处理、不会统计、更不会做可视化图表&#xff1f; 其实根本不用懂编程、不用啃复杂专业知识&#xff0c;普通小白也能零基础玩转气象数据&#xff0c;从数据整理、基础统计到出专业好看的成品图&#xff0c;新手也能一键拿…...

嵌入式系统调试技术:从JTAG到多核同步的实战指南

1. 嵌入式系统调试技术概述在嵌入式系统开发过程中&#xff0c;调试环节往往占据整个开发周期的40%-60%时间。与通用计算机系统不同&#xff0c;嵌入式系统通常运行在资源受限的环境中&#xff0c;缺乏标准输入输出设备&#xff0c;这使得调试工作更具挑战性。我曾参与过多个工…...

手把手教你用Simulink搭建BUCK电路:从主电路到PID整定的保姆级流程

手把手教你用Simulink搭建BUCK电路&#xff1a;从主电路到PID整定的保姆级流程 电力电子技术作为现代能源转换的核心&#xff0c;BUCK电路因其高效的降压特性被广泛应用于电源设计领域。对于初学者而言&#xff0c;理论知识与实际仿真之间往往存在一道难以跨越的鸿沟——明明理…...

设计师连夜删稿的真相:Onion Skin未启用导致版本错位!3分钟紧急修复+历史帧自动锚定脚本

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;设计师连夜删稿的真相&#xff1a;Onion Skin未启用导致版本错位&#xff01;3分钟紧急修复历史帧自动锚定脚本 当动画师在 Toon Boom Harmony 或 Adobe Animate 中反复导出“看似正确”的中间帧&#…...

Midjourney水彩风提示词已进入“语义过载”危机?2024Q2最新精简指令集发布(仅保留11个高响应关键词,准确率提升63.8%)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Midjourney水彩风提示词的语义过载现象本质解析 水彩风格生成中&#xff0c;“watercolor”、“gouache”、“loose brushstrokes”、“wet-on-wet”等提示词常被叠加使用&#xff0c;表面增强风格表征…...

告别疲劳计算烦恼:用nCode DesignLife搞定汽车悬架非线性载荷分析(附信号处理技巧)

告别疲劳计算烦恼&#xff1a;用nCode DesignLife搞定汽车悬架非线性载荷分析&#xff08;附信号处理技巧&#xff09; 悬架系统作为汽车底盘的核心部件&#xff0c;其疲劳寿命直接关系到整车可靠性与安全性。但在实际工程分析中&#xff0c;工程师们常常被一个棘手问题困扰&am…...

太流批了,发票合并神器

今天给大家推荐两款软件&#xff0c;一款是图片转PDF&#xff0c;一款是发票合并工具。有需要的小伙伴可以下载收藏。 第一款&#xff1a;png2pdf png2pdf是一款png图片转PDF的小工具&#xff0c;这类的工具之前也有推荐过&#xff0c;但是今天这款比较特殊。 只要把图片拖入软…...

从HIP4082到IR2184:直流电机H桥驱动芯片怎么选?一份给硬件工程师的对比清单(含成本、功耗、设计复杂度)

从HIP4082到IR2184&#xff1a;直流电机H桥驱动芯片的工程选型指南 在小型机器人、电动工具或自动化设备的开发中&#xff0c;电机驱动电路的设计往往是硬件工程师面临的核心挑战之一。面对市场上琳琅满目的驱动芯片&#xff0c;如何在性能、成本和可靠性之间找到最佳平衡点&am…...

如何彻底解决Windows风扇控制难题:Fan Control完整指南

如何彻底解决Windows风扇控制难题&#xff1a;Fan Control完整指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/f…...

Android Input与SendEvent脚本命令在自动化测试中的性能优化实践

1. Android输入事件模拟的两种核心方式 在Android自动化测试领域&#xff0c;模拟用户输入操作是基础中的基础。我经历过无数次深夜调试&#xff0c;最终发现真正高效的输入模拟离不开对底层原理的深入理解。目前主流的两种方式是Input命令和SendEvent脚本&#xff0c;它们就像…...