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方法即可。
setRelation 是 QSqlRelationalTableModel 类中的一个方法,用于设置模型中某一列的关联关系。这个方法的目的是告诉模型某一列的值在另一个表中有关联,并提供相关的信息,以便在视图中显示更有意义的数据而不是外键的原始值。
以下是 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关联表组件的更多相关文章
- C/C++ Qt 数据库SqlRelationalTable关联表
在上一篇博文中详细介绍了SqlTableModle组件是如何使用的,本篇博文将介绍SqlRelationalTable关联表组件,该组件其实是SqlTableModle组件的扩展类,SqlRelati ...
- C语言 C++1X STL QT免费视频课程 QT5界面开发美化 式样表 QML
C/C++/QT界面开发界面美化视频课程系列 课程1 C语言 C++1X STL QT免费视频课程 QT5界面开发美化 式样表 QML 返回顶部 课程1 C语言 C++1X STL QT免费视 ...
- Yii 1开发日记 -- 后台搜索功能下拉及关联表搜索
Yii 1 实现后台搜索,效果如下: 一. 下拉搜索: 1.模型中和常规的一样 if (isset($_GET['agency']['status']) && $_GET['agenc ...
- PyQt(Python+Qt)入门:Designer组件属性编辑界面中QWidget类相关属性详解
本文适用人员:本文比较长,适合不理解Qt Designer部件属性的人员阅读或资料查找. 声明: 1.如果有人认为本文是简单的复制粘贴+翻译而成,敬请读本文最后的后记: 2.本文为老猿Python学习 ...
- 【应用笔记】【AN005】Qt开发环境下基于RS485的4-20mA电流采集
简介 4-20mA电流环具有广泛的应用前景,在许多行业中都发挥着重要作用.本文主要介绍在Qt开发环境下基于RS485实现4-20mA电流采集,实现WINDOWS平台对数据的采集.分析及显示. 系统组成 ...
- Qt开发北斗定位系统融合百度地图API及Qt程序打包发布
Qt开发北斗定位系统融合百度地图API及Qt程序打包发布 1.上位机介绍 最近有个接了一个小型项目,内容很简单,就是解析北斗GPS的串口数据然后输出经纬度,但接过来觉得太简单,就发挥了主观能动性,增加 ...
- 循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码
VUE+Element 前端应用,比较不错的一点就是界面组件化,我们可以根据重用的指导方针,把界面内容拆分为各个不同的组合,每一个模块可以是一个组件,也可以是多个组件的综合体,而且这一个过程非常方便. ...
- Qt开发的应用记录读取用户习惯设置的方法
Qt开发的应用记录读取用户习惯设置的方法 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/w ...
- Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架(2)
Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架 注:本文更多地是带着如何去思考答案,而不是纯粹的放一个答案上来,如果你需要直接看到完整的答案,请直接看实例和最后的 ...
- Rafy 领域实体框架 - 树型实体功能(自关联表)
在 Rafy 领域实体框架中,对自关联的实体结构做了特殊的处理,下面对这一功能进行讲解. 场景 在开发数据库应用程序时,往往会遇到自关联表的场景.例如,分类信息.组织架构中的部门.文件夹信息等,都 ...
随机推荐
- BZ全景可视化编辑器 (KRPano可视化编辑器, 无需编写任何代码制作全景漫游)
软件简介 BZ全景编辑器是一款KRPano全景可视化编辑工具,下载安装即可使用,无需拥有任何KRPano代码基础,便可以制作生成精美的全景漫游作品. 官方网站: 点击进入官方网站 最新版软件下载地址: ...
- web应用及微信小程序版本更新检测方案实践
背景: 随着项目体量越来越大,用户群体越来越多,用户的声音也越来越明显:关于应用发版之后用户无感知,导致用户用的是仍然还是老版本功能,除非用户手动刷新,否则体验不到最新的功能:这样的体验非常不好,于是 ...
- 「codeforces - 585E」Present for Vitalik the Philatelist
link. 设 \(\displaystyle f(x) = \# S', s.t. S' \subseteq S, S' \neq \varnothing, \gcd(S') = x\),\(g(x ...
- Solution -「BalticOI 2004」Sequence
Description Link. Given is a sequencen \(A\) of \(n\) intergers. Construct a stricly increasing sequ ...
- Python爬虫如何使用代理IP进行抓取
前言 Python爬虫是一种非常强大的工具,可以用于抓取各种网站的数据.但是,在一些情况下,我们需要使用代理IP来完成数据抓取,如绕过IP限制或保护隐私信息等.本文将介绍如何使用Python爬虫抓取数 ...
- 关于初次new springboot项目
如果是新手初学,然后做springboot项目报各种错,改来改去最终都无法出现successful字样. 请先检查,maven环境是否配好. maven环境决定你下载依赖的速度,以及能否下载成功. m ...
- fepk文件格式说明
1 卫星影像金字塔分块原理说明 通常我们在工作中使用的卫星影像数据,轻则几百M,重则几百个G甚至上TB级.影像数据太大,是大家经常会遇到的一个问题,尤其是想下载一个省以上数据的时候该问题尤为突出.那 ...
- Linux系列教程——Shell、Linux文件管理
文章目录 Shell 1.什么是Bash shell(壳) 2.Bash Shell能干什么? 3.平时我们如何使用Shell呢? 4.Shell提示符 5.Shell基础语法 2.Bash Shel ...
- GO语言基础之基本运算符
GO语言基础之基本运算符 目录 GO语言基础之基本运算符 一.运算符 内置运算符: 二.算术运算符 三.关系运算符 四.逻辑运算符 五.位运算符 六.赋值运算符 一.运算符 作用:运算符用于在程序运行 ...
- python第一章 学习笔记 计算机基础知识 Sublime Text 3
## 计算机是什么 在现实生活中,越来越无法离开计算机了 电脑.笔记本.手机.游戏机.汽车导航.智能电视 ... 计算机就是一个用来计算的机器! 目前来讲,计算机只能根据人类的指令来完成各种操作,人让 ...