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

Qt数据库操作-QSqlQueryModel 的使用

QSqlQueryModel 功能概述

QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能,但是 QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据。QSqlQueryModel 类的主要函数如下:

接口函数功能描述
void clear()清除数据模型,释放所有获得的数据
QSqlError lastError()返回上次的错误,可以获取错误的类型和文本信息
QSqlQuery query()返回当前关联的 QSqlQuery 对象
void setQuery(QSqlQuery& query)设置一个 QSqlQuery 对象,获取数据
void setQuery(QString& query)设置一个 SELECT 语句创建查询,获取数据
QSqlRecord record()返回一个空记录,包含当前查询的字段信息
QSqlRecord record(int row)返回行号为 row 的记录
int rowCount()返回查询到的记录条数
int columnCount()返回查询的字段个数
void setHeaderData(int section, Qt::Orientation orientation, QVariant& value)设置表头数据,一般用于设置字段的表头标题

使用 QSqlQueryModel 作为数据模型从数据库查询数据,只需要使用 setQuery() 函数设置一个 SELECT 查询语句即可。QSqlQueryModel 可以作为 QTableView 等视图组件的数据源,也可以使用 QDataWidgetMapper 创建字段与界面组件的映射,只是查询出来的数据是不可编辑的。

使用 QSqlQueryModel 实现数据查询

实例功能

image.png

使用 QSqlQueryModel 可以从一个数据表或多个数据表里查询数据,只要设计好 SELECT 语句即可。由于 QSqlQueryModel 读出的数据是只读的,所以没有编辑保存等功能,主窗口定义如下:

class MainWindow : public QMainWindow
{Q_OBJECTprivate:QLabel  *LabInfo;QSqlDatabase  DB; //数据库QSqlQueryModel  *qryModel; //数据模型QItemSelectionModel *theSelection; //选择模型QDataWidgetMapper   *dataMapper;//数据界面映射void    openTable();//打开数据表void    refreshTableView();//移动记录时刷新TableView的当前行
public:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:// QTableView的SelectionModel的行发生了变化,进行处理void on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
///void on_actOpenDB_triggered();void on_actRecFirst_triggered();void on_actRecPrevious_triggered();void on_actRecNext_triggered();void on_actRecLast_triggered();private:Ui::MainWindow *ui;
};

这里定义了 QSqlQueryModel 类型的数据模型变量 qryModel,也定义了数据库、选择模型和数据界面映射的变量。refreshTableView() 函数用于记录移动后刷新 TableView 上的当前行位置。自定义槽函数 on_currentRowChanged() 在选择模型的当前变化时,处理 Photo 字段的查询与照片显示。

打开数据库

openTable() 用于查询数据,简历界面显示等具体操作,代码如下:

void MainWindow::openTable()
{//打开数据表qryModel=new QSqlQueryModel(this);qryModel->setQuery("SELECT empNo, Name, Gender, Height, Birthday, Mobile, Province, City, Department, "" Education, Salary FROM employee ORDER BY empNo");if (qryModel->lastError().isValid()){QMessageBox::critical(this, "错误", "数据表查询错误,错误信息\n"+qryModel->lastError().text(),QMessageBox::Ok,QMessageBox::NoButton);return;}LabInfo->setText(QString::asprintf("记录条数:%d",qryModel->rowCount()));qryModel->setHeaderData(0,Qt::Horizontal,"工号");qryModel->setHeaderData(1,Qt::Horizontal,"姓名");qryModel->setHeaderData(2,Qt::Horizontal,"性别");qryModel->setHeaderData(3,Qt::Horizontal,"身高");qryModel->setHeaderData(4,Qt::Horizontal,"出生日期");qryModel->setHeaderData(5,Qt::Horizontal,"手机");qryModel->setHeaderData(6,Qt::Horizontal,"省份");qryModel->setHeaderData(7,Qt::Horizontal,"城市");qryModel->setHeaderData(8,Qt::Horizontal,"部门");qryModel->setHeaderData(9,Qt::Horizontal,"学历");qryModel->setHeaderData(10,Qt::Horizontal,"工资");theSelection=new QItemSelectionModel(qryModel);//选择行变化时connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));ui->tableView->setModel(qryModel);ui->tableView->setSelectionModel(theSelection);
//    ui->tableView->resizeColumnsToContents();
//    ui->tableView->horizontalHeader()->setStretchLastSection(true);//创建数据映射dataMapper= new QDataWidgetMapper();dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);dataMapper->setModel(qryModel);dataMapper->addMapping(ui->dbSpinEmpNo,0);//"empNo";dataMapper->addMapping(ui->dbEditName,1);//"Name";dataMapper->addMapping(ui->dbComboSex,2);//"Gender";dataMapper->addMapping(ui->dbSpinHeight,3);//"Height";dataMapper->addMapping(ui->dbEditBirth,4);//"Birthday";dataMapper->addMapping(ui->dbEditMobile,5);//"Mobile";dataMapper->addMapping(ui->dbComboProvince,6);//"Province";dataMapper->addMapping(ui->dbEditCity,7);//"City";dataMapper->addMapping(ui->dbComboDep,8);//"Department";dataMapper->addMapping(ui->dbComboEdu,9);//"Education";dataMapper->addMapping(ui->dbSpinSalary,10);//"Salary";dataMapper->toFirst();ui->actOpenDB->setEnabled(false);
}

程序首先创建了 QSqlQueryModel 类型的私有变量 qryModel,然后调用 setQuery() 函数设置了 SELECT 查询语句,SELECT 语句从 employee 表里查询除了 Memo 和 Photo 之外的所有其他字段。使用 setHeadData() 函数为每个字段设置显示标题,为了代码简化,这里直接使用字段的序号。
qryModel 创建了选择模型 theSelection,并将其 currentRowChanged() 信号和自定义槽函数关联,查询出数据显示在界面上,槽函数代码如下:

void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{Q_UNUSED(previous);if (!current.isValid()){ui->dbLabPhoto->clear();return;}dataMapper->setCurrentModelIndex(current);bool first=(current.row()==0); //是否首记录bool last=(current.row()==qryModel->rowCount()-1);//是否尾记录ui->actRecFirst->setEnabled(!first); //更新使能状态ui->actRecPrevious->setEnabled(!first);ui->actRecNext->setEnabled(!last);ui->actRecLast->setEnabled(!last);int curRecNo=theSelection->currentIndex().row();QSqlRecord  curRec=qryModel->record(curRecNo); //获取当前记录int empNo=curRec.value("EmpNo").toInt();QSqlQuery query; //查询当前empNo的Memo和Photo字段的数据query.prepare("select EmpNo, Memo, Photo from employee where EmpNo = :ID");query.bindValue(":ID",empNo);query.exec();query.first();QVariant    va=query.value("Photo");//if (!va.isValid())  //图片字段内容为空ui->dbLabPhoto->clear();else{//显示照片QByteArray data=va.toByteArray();QPixmap pic;pic.loadFromData(data);ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));}QVariant    va2=query.value("Memo");//显示备注ui->dbEditMemo->setPlainText(va2.toString());
}

记录移动

用于数据映射的 QDataWidgetMapper 类设置数据模型后,总是指向数据模型的当前记录。QDataWidgetMapper 有四个函数进行当前记录移动,分别是 toFirst()toLast()toNext()toPrevious()。当前记录移动时,会引起数据模型关联的选择模型发射 currentRowChanged() 信号,触发槽函数。工具栏的四个移动按钮代码如下:

void MainWindow::on_actRecFirst_triggered()
{ //首记录dataMapper->toFirst();refreshTableView();
}void MainWindow::on_actRecPrevious_triggered()
{ //前一条记录dataMapper->toPrevious();refreshTableView();
}void MainWindow::on_actRecNext_triggered()
{//后一条记录dataMapper->toNext();refreshTableView();
}void MainWindow::on_actRecLast_triggered()
{//最后一条记录dataMapper->toLast();refreshTableView();
}

参考资料:https://github.com/0voice

相关文章:

Qt数据库操作-QSqlQueryModel 的使用

QSqlQueryModel 功能概述 QSqlQueryModel 是 QSqlTableModel 的父类。QSqlQueryModel 封装了执行 SELECT 语句从数据库查询数据的功能,但是 QSqlQueryModel 只能作为只读数据源使用,不可以编辑数据。QSqlQueryModel 类的主要函数如下: 接口…...

C语言编程1.21波兰国旗问题

题目描述 桌上有 n ( 1 < n < 10000 ) 面小旗&#xff0c;一部分是白旗&#xff0c;一部分是红旗(波兰国旗由白色和红色组成)。唯一允许的操作是交换两面小旗位置。请你设计一个算法&#xff0c;用最少的交换操作将所有的白旗都置于红旗的之前。 输入格式 第一行为一个…...

如何利用微型5G网关为智慧无人矿车提供精确定位

随着5G、AI、物联网技术的发展和普及&#xff0c;越来越多行业正在加快生产、运营、管理的无人化、数字化与智能化&#xff0c;以适应当前我国“智慧、绿色、低碳”的新型发展模式需要。其中矿产业就是典型场景之一。针对矿山场景的智慧化、无人化转型&#xff0c;佰马提供基于…...

使用docker-compese部署SFTPGo详解

官网&#xff1a;SFTP & FTP as a Managed Service (SaaS) and On-premise 一、SFTPGo简介 SFTPGo 是一款功能强大的文件传输服务器软件。它支持多种协议&#xff08;SFTP、SCP、FTP/S、WebDAV、HTTP/S&#xff09;和多个存储后端。 借助 SFTPGo&#xff0c;您可以利用本地…...

Ajax基础总结(思维导图+二维表)

一些话 刚开始学习Ajax的时候&#xff0c;感觉很模糊&#xff0c;但是好像学什么都是这样的&#xff0c;很正常&#xff0c;但是当你学习的时候要持续性敲代码&#xff0c;边敲代码其实就可以理解很多了。然后在最后的总结&#xff0c;其实做二维表之后&#xff0c;就可以区分…...

Spring Task和WebSocket使用

在现代 Web 应用中&#xff0c;WebSocket 作为一种全双工通信协议&#xff0c;为实时数据传输提供了强大的支持。若要确保 WebSocket 在生产环境中的稳定性和性能&#xff0c;使用 Nginx 作为反向代理服务器是一个明智的选择。本篇文章将带你了解如何在 Nginx 中配置 WebSocket…...

微信小程序 本地调试和vconsole可以 但在体验上页面不请求数据

微信小程序页面不请求数据 本地调试和vconsole可以 但在体验版页面不请求数据&#xff0c;如遇到这类问题基本都是一样的解决办法 1、如何调试找到问题 首先要把小程序本地设置的不校验合法域名关掉&#xff0c;不然本地一直都是好的 然后通过本地真机调试打断点找到问题位…...

QT:将QTableWidget内容写入txt文件中

文章详请&#xff1a;最近在做手在眼上的标定&#xff0c;首先要采集机械臂数据和图像数据&#xff0c;我使用tablewidget进行机械臂数据的显示&#xff0c;最后的计算需要将机械臂位姿数据存储在txt文件中。 引用&#xff1a;Qt如何保存tableWidget数据&#xff1f;_qt table…...

前端面试题(六)

1.let,var,const区别 1.作用域&#xff1a;  var&#xff1a;var声明的变量存在函数作用域或全局作用域&#xff0c;这意味着它们在声明它们的函数内部可见&#xff0c;而不在块级作用域内可见。 let和const&#xff1a;let和const声明的变量存在块级作用域&#xff0c;这…...

「Mac畅玩鸿蒙与硬件35」UI互动应用篇12 - 简易日历

本篇将带你实现一个简易日历应用&#xff0c;显示当前月份的日期&#xff0c;并支持选择特定日期的功能。用户可以通过点击日期高亮选中&#xff0c;还可以切换上下月份&#xff0c;体验动态界面的交互效果。 关键词 UI互动应用简易日历动态界面状态管理用户交互 一、功能说明…...

Leetcode581. 最短无序连续子数组(HOT100)

链接 我的代码&#xff1a; class Solution { public:int findUnsortedSubarray(vector<int>& nums) {vector<int> res nums;sort(res.begin(),res.end());int l 0,r nums.size()-1;while(nums[l]res[l]){l;if(lnums.size()){return 0;}}while(nums[r]res…...

HTML前端开发-- Flex布局详解及实战

引言 Flex布局&#xff0c;全称为Flexible Box Layout&#xff0c;是一种现代CSS布局技术&#xff0c;它提供了一种更有效的方式来设计响应式布局和复杂页面布局。本文将详细介绍Flex布局的基本概念、属性以及实战应用。 一、基本概念 Flex布局的核心是Flex容器&#xff08;…...

基于JWT跨语言开发分布式业务系统的挑战与实践:多语言协作的最佳方案

在现代分布式架构下&#xff0c;开发团队往往由来自不同技术栈和开发语言的工程师组成。如何有效地管理这些开发人员的协作&#xff0c;尤其是在实现跨语言的认证与授权机制时&#xff0c;成为了开发者面临的一个重大挑战。JSON Web Token&#xff08;JWT&#xff09;作为一种轻…...

二分法篇——于上下边界的扭转压缩间,窥见正解辉映之光(2)

前言 上篇介绍了二分法的相关原理并结合具体题目进行讲解运用&#xff0c;本篇将加大难度&#xff0c;进一步强化对二分法的掌握。 一. 寻找峰值 1.1 题目链接&#xff1a;https://leetcode.cn/problems/find-peak-element/description/ 1.2 题目分析: 题目要求返回数组内…...

什么是 Kata Containers?

什么是 Kata Containers&#xff1f; Kata Containers 是一种结合了容器技术和虚拟机技术的轻量级运行时&#xff0c;旨在提供容器的速度和虚拟机的安全性。它将容器运行在一个隔离的虚拟机中&#xff0c;从而大幅提升安全性&#xff0c;同时保持容器的高效性。 Kata Contain…...

SpringMvc项目配置RabbitMq

前言&#xff1a;只有消费者部分&#xff0c;没有记录生产者部分 结构图 配置类 可以xml配置&#xff0c;也可以配置类&#xff0c;二者可以相互转化。两种bean注入的方式。 import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.spring…...

shell编程(4)脚本与用户交互以及if条件判断

shell编程&#xff08;4&#xff09;脚本与用户交互以及if条件判断 声明&#xff01; 学习视频来自B站up主 ​泷羽sec​​ 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;…...

vue2组件跨层级数据共享provide 和 inject

在 Vue 2 中&#xff0c;provide 和 inject 的功能也是可以使用的&#xff0c;虽然在 Vue 3 中它们成为了组合式 API 的一部分。在 Vue 2 中&#xff0c;provide 和 inject 主要是用于祖先组件和后代组件之间的数据共享&#xff0c;而不是通过 props 和 emit 逐层传递。 Vue 2…...

springboot/ssm校园闲置物品交易系统ava大学生二手闲置交易平台web二手源码

springboot/ssm校园闲置物品交易系统ava大学生二手闲置交易平台web二手源码 基于springboot(可改ssm)htmlvue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数…...

Redis实现限量优惠券的秒杀

核心&#xff1a;避免超卖问题&#xff0c;保证一人一单 业务逻辑 代码步骤分析 全部代码 Service public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {Resourceprivate ISeckillVoucher…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

JS红宝书笔记 - 3.3 变量

要定义变量&#xff0c;可以使用var操作符&#xff0c;后跟变量名 ES实现变量初始化&#xff0c;因此可以同时定义变量并设置它的值 使用var操作符定义的变量会成为包含它的函数的局部变量。 在函数内定义变量时省略var操作符&#xff0c;可以创建一个全局变量 如果需要定义…...