QT 使用QSqlTableModel对数据库进行创建,插入,显示

news2025/2/26 11:42:45

文章目录

      • 效果图
      • 概述
      • 功能点
      • 代码分析
        • 初始数据
        • 插入数据
        • 数据显示
      • 总结

效果图

请添加图片描述

概述

  • 本案例用于对数据库中的数据进行显示等其他操作,其他表格筛选,过滤等功能可看此博客

  • 框架:数据模型使用QSqlTableModel,视图使用QTableView,表格的一些字体或者控件之类的使用QStyledItemDelegate实现。
    导航栏的变化实时的传回给表格,所有的数据库表都实现继承一个表格类,根据表格本身的特性可以设置自己的委托。数据库使用一个单列类进行管理,包括数据库的读取 ,创建,数据插入,以及对模型的映射等。

  • 使用的数据库类型为QPSQL

功能点

  1. 初始化数据
  2. 插入数据
  3. 数据显示

代码分析

初始数据
  • 初始化数据库及表
    void LogManagement::initDB()
    {
        dataPtr->db = QSqlDatabase::addDatabase("QPSQL", "dabao_pouring__db_connection");
        dataPtr->db.setHostName("localhost");
        dataPtr->db.setDatabaseName("dabao_pouring_db");
        dataPtr->db.setUserName("postgres");
        dataPtr->db.setPassword("dj");
    
        if (!dataPtr->db.open())
        {
            qCritical() << "无法打开数据库:" << dataPtr->db.lastError().text();
            return;
        }
        initOperationLog();
        initErrorLog();
    }
    
    void LogManagement::initOperationLog()
    {
        QScopedPointer<QSqlQuery> query(new QSqlQuery(dataPtr->db));
        if (!query->exec("SELECT 1 FROM operationlog LIMIT 1"))
        {
            QString createTableQuery = R"(
            CREATE TABLE IF NOT EXISTS operationlog (
                id SERIAL PRIMARY KEY,
                time TIMESTAMP NOT NULL,
                result VARCHAR(10) NOT NULL,
                content TEXT NOT NULL,
                error TEXT  NULL,
                operation VARCHAR(10) NULL
            )
        )";
    
            if (!query->exec(createTableQuery))
            {
                qCritical() << "创建表失败:" << query->lastError().text();
                return;
            }
        }
    
        dataPtr->operationLogModel = new QSqlTableModel(this, dataPtr->db);
        dataPtr->operationLogModel->setTable("operationlog");                        // 设置要操作的表名
        dataPtr->operationLogModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略
        if (!(dataPtr->operationLogModel->select()))                                 // 查询数据
        {
            qCritical() << "打开数据表失败:" << dataPtr->operationLogModel->lastError().text();
            return;
        }
    
        dataPtr->operationLogModel->setHeaderData(dataPtr->operationLogModel->fieldIndex("time"), Qt::Horizontal, "时间");
        dataPtr->operationLogModel->setHeaderData(dataPtr->operationLogModel->fieldIndex("result"), Qt::Horizontal, "操作情况");
        dataPtr->operationLogModel->setHeaderData(dataPtr->operationLogModel->fieldIndex("content"), Qt::Horizontal, "操作内容");
        dataPtr->operationLogModel->setHeaderData(dataPtr->operationLogModel->fieldIndex("error"), Qt::Horizontal, "异常");
        dataPtr->operationLogModel->setHeaderData(dataPtr->operationLogModel->fieldIndex("operation"), Qt::Horizontal, "操作");
    }
    
插入数据

void LogManagement::appendErrorLogData(const QString &time, const QString &type, const QString &content)
{
    if (!dataPtr->errorLogModel)
        return;
    int newRow = dataPtr->errorLogModel->rowCount();      // 获取当前行数,这将是新行的索引
    bool res = dataPtr->errorLogModel->insertRow(newRow); // 插入新行
    if (!res)
    {
        qCritical() << "无法添加新记录";
        return;
    }

    // 设置新记录的值
    res = dataPtr->errorLogModel->setData(dataPtr->errorLogModel->index(newRow, dataPtr->errorLogModel->fieldIndex("type")), type);
    if (!res)
    {
        return;
    }
    res = dataPtr->errorLogModel->setData(dataPtr->errorLogModel->index(newRow, dataPtr->errorLogModel->fieldIndex("time")), QDateTime::fromString(time, "yyyy-MM-dd hh:mm:ss"));
    if (!res)
    {
        return;
    }
    res = dataPtr->errorLogModel->setData(dataPtr->errorLogModel->index(newRow, dataPtr->errorLogModel->fieldIndex("content")), content);
    if (!res)
    {
        return;
    }

    // 提交新记录
    res = dataPtr->errorLogModel->submitAll();
    if (!res)
    {
        qCritical() << "保存记录失败: " << dataPtr->errorLogModel->lastError().text();
        dataPtr->errorLogModel->revertAll(); // 如果提交失败,回滚所有更改
    }
}

数据显示
  • 使用的是model-view的设计模式,对于一些特殊的数据显示,比较字体颜色,或者加入删除按钮之类,由于数据都来源于model,所以设置操作按钮之类的并不好直接实现,我想到的一个办法就是,在数据库表的最后一列插入一个空列,用于放置操作按钮,比如删除。
    void GeneralDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
    {
        QStyledItemDelegate::initStyleOption(option, index);
    
        QVariant data = index.model()->data(index, Qt::EditRole);
        if (data.type() == QVariant::DateTime)
        {
            QDateTime dateTime = data.toDateTime();
            option->displayAlignment = Qt::AlignCenter;
            option->text = dateTime.toString("yyyy-MM-dd hh:mm:ss");
        }
        else if (data.type() == QVariant::Int)
        {
            option->displayAlignment = Qt::AlignRight;
            option->text = QString::number(data.toInt());
        }
        else
        {
            option->displayAlignment = Qt::AlignLeft;
            option->text = data.toString();
        }
    }
    
    void GeneralDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        int currentColumn = index.column();
        int columnCount = index.model()->columnCount();
        // 判断是否为最后一列
        bool isLastColumn = (currentColumn == columnCount - 1);
        if (isLastColumn)
        {
            QRect buttonRect = option.rect.adjusted(2, 2, -2, -2); // 调整按钮位置和大小
            QStyleOptionButton buttonOption;
            buttonOption.rect = buttonRect;
            buttonOption.state |= QStyle::State_Enabled;
            buttonOption.state |= QStyle::State_MouseOver;
            buttonOption.palette.setBrush(QPalette::Button, QColor(Qt::red));
            buttonOption.text = "删除";
    
            painter->save();
            painter->setClipRect(buttonRect);
            QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
            painter->restore();
        }
        else
        {
            QStyleOptionViewItem options = option;
            initStyleOption(&options, index);
            options.displayAlignment = Qt::AlignCenter; // 居中
            QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
        }
    }
    
    bool GeneralDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
    {
        int currentColumn = index.column();
        int columnCount = index.model()->columnCount();
        // 判断是否为最后一列
        bool isLastColumn = (currentColumn == columnCount - 1);
        if (event->type() == QEvent::MouseButtonRelease && isLastColumn)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
            QRect buttonRect = option.rect.adjusted(2, 2, -2, -2);
            if (buttonRect.contains(mouseEvent->pos()))
            {
                // 触发删除操作
                emit deleteRequested(index);
                return true;
            }
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }
    

总结

  • 知识理应共享,源码在此

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

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

相关文章

Vscode:问题解决办法 及 Tips 总结

Visual Studio Code&#xff08;简称VSCode&#xff09;是一个功能强大的开源代码编辑器&#xff0c;广泛用于各种编程语言和开发场景&#xff0c;本博客主要记录在使用 VSCode 进行verilog开发时遇到的问题及解决办法&#xff0c;使用过程中的技巧 文章目录 扩展安装失败调试配…

FANUC机器人系统镜像备份与恢复的具体步骤(图文)

FANUC机器人系统镜像备份与恢复的具体步骤(图文) 镜像备份: 如下图所示,进入文件—工具—切换设备,找到插入的U盘UT1, 如下图所示,进入U盘目录后,创建目录,这里目录名称为11, 如下图所示࿰

模块化架构与微服务架构,哪种更适合桌面软件开发?

前言 在现代软件开发中&#xff0c;架构设计扮演着至关重要的角色。两种常见的架构设计方法是模块化架构与微服务架构。它们各自有独特的优势和适用场景&#xff0c;尤其在C#桌面软件开发领域&#xff0c;模块化架构往往更加具有实践性。本文将对这两种架构进行对比&#xff0…

使用Flask和Pydantic实现参数验证

使用Flask和Pydantic实现参数验证 1 简介 Pydantic是一个用于数据验证和解析的 Python 库&#xff0c;版本2的性能有较大提升&#xff0c;很多框架使用Pydantic做数据校验。 # 官方参考文档 https://docs.pydantic.dev/latest/# Github地址 https://github.com/pydantic/pyd…

游戏引擎学习第81天

仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中&#xff0c;讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分&#xff0c;因为当时主要的工作重心不在这里&#xff0c;但在实现过程中&#xff0c;发现地…

【Vue3 入门到实战】3. ref 和 reactive区别和适用场景

目录 ​编辑 1. ref 部分 1.1 ref定义基本数据类型 1.2 ref 定义引用数据类型 2. reactive 函数 3. ref 和 reactive 对比 3.1 原理 3.2 区别 3.3 使用原则 在 Vue 3 中 ref 和 reactive 是用于创建响应式数据的两个核心函数。它们都属于 Composition API 的一部分&…

蓝桥杯3525 公因数匹配 | 枚举+数学

题目传送门 这个题目是一个数学题&#xff0c;由于只需要找到存在大于1的公因数的两数&#xff0c;所以比较方便的做法是统计每一个数的&#xff08;质&#xff09;因数。可以通过筛法统计质因数降低复杂度&#xff0c;但是直接枚举因数也可以满足要求。使用字典记录每个因数出…

django应急物资管理系统

Django应急物资管理系统是一种高效、智能的管理系统&#xff0c;旨在应对自然灾害、事故灾难等突发事件&#xff0c;确保救援物资能够及时、准确地调配到需要的地方。 一、系统背景与意义 在现代社会&#xff0c;各类突发事件频繁发生&#xff0c;对人民生命财产安全构成严重…

python+django+Nacos实现配置动态更新-集中管理配置(实现mysql配置动态读取及动态更新)

一、docker-compose.yml 部署nacos服务 version: "3" services:mysql:container_name: mysql# 5.7image: mysql:5.7environment:# mysql root用户密码MYSQL_ROOT_PASSWORD: rootTZ: Asia/Shanghai# 初始化数据库(后续的初始化sql会在这个库执行)MYSQL_DATABASE: nac…

Qt Desiogn生成的ui文件转化为h文件

1.找到这个工具 2.查找到ui文件以及要转化为的h文件的路径。 3.在1中的工具输入uic /xx/xxx.ui -o /xx/xxx.h即可得到结果。

vim文本编辑器

vim命令的使用&#xff1a; [rootxxx ~]# touch aa.txt #首先创建一个文件 [rootxxx ~]# vim aa.txt #vim进入文件aa.txt进行编辑 vim是vi的升级版&#xff0c;具有以下三种基本模式&#xff1a; 输入模式(编辑模式) 点击i进入编辑模式 &#xff08;说明…

大华Java开发面试题及参考答案 (上)

TCP 的三次握手和四次挥手过程中各个状态的细节是怎样的&#xff1f; TCP&#xff08;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的传输层协议&#xff0c;其三次握手和四次挥手过程涉及多个状态&#xff0c;以下是详细的状态细节&#xff1a; 三次握手…

乐乐音乐Compose-Desktop版

简介 乐乐音乐Compose-Desktop版主要是基于Compose-Desktop框架和musique开发的音乐播放器&#xff0c;它支持lrc歌词和动感歌词( ksc歌词、krc歌词、trc歌词、zrce歌词和hrc歌词等)、多种格式歌词转换器及制作动感歌词、翻译歌词和音译歌词。 编译环境 ideaIU-2024.1.4、JD…

HTML5 教程(下)

HTML5 Video(视频) HTML5 Video(视频) 在本节内容中&#xff0c;你将了解到在HTML5中视频是如何工作的、主流浏览器支持的视频格式以及如何对网页中的视频进行控制。 很多站点都会使用到视频. HTML5 提供了展示视频的标准。 检测您的浏览器是否支持 HTML5 视频&#xff1a; …

计算机网络 (51)鉴别

前言 计算机网络鉴别是信息安全领域中的一项关键技术&#xff0c;主要用于验证用户或信息的真实性&#xff0c;以及确保信息的完整性和来源的可靠性。 一、目的与重要性 鉴别的目的是验明用户或信息的正身&#xff0c;对实体声称的身份进行唯一识别&#xff0c;以便验证其访问请…

力扣 有效的括号

括号匹配问题&#xff0c;找到符合的进行抵消。 题目 从题可以看出是嵌套的括号先匹配先做抵消&#xff0c;类似就近原则&#xff0c;这也是栈的典型例题。可以通过枚举多种不同的情况慢慢用if与else做返回。 时间复杂度&#xff1a;O(n)&#xff0c;其中 n 是字符串的长度。…

阿里云通义实验室自然语言处理方向负责人黄非:通义灵码2.0,迈入 Agentic AI

通义灵码是基于阿里巴巴通义大模型研发的AI 智能编码助手&#xff0c;在通义灵码 1.0 时代&#xff0c;我们针对代码的生成、补全和问答&#xff0c;通过高效果、低时延&#xff0c;研发出了国内最受欢迎的编码助手。 在通义灵码 2.0 发布会上&#xff0c;阿里云通义实验室自然…

深度学习模块C2f代码详解

C2f 是一个用于构建卷积神经网络&#xff08;CNN&#xff09;的模块&#xff0c;特别是在 YOLOv5 和 YOLOv8 等目标检测模型中。这个模块是一个改进的 CSP&#xff08;Cross Stage Partial&#xff09;Bottleneck 结构&#xff0c;旨在提高计算效率和特征提取能力。下面是对 C2…

TOSUN同星TsMaster使用入门——3、使用系统变量及c小程序结合panel面板发送报文

本篇内容将介绍TsMaster中常用的Panel面板控件以及使用Panel控件通过系统变量以及c小程序来修改信号的值&#xff0c;控制报文的发送等。 目录 一、常用的Panel控件介绍 1.1系统——启动停止按钮 1.2 显示控件——文本框 1.3 显示控件——分组框 1.4 读写控件——按钮 1.…

C++,设计模式,【目录篇】

文章目录 1. 简介2. 设计模式的分类2.1 创建型模式&#xff08;Creational Patterns&#xff09;&#xff1a;2.2 结构型模式&#xff08;Structural Patterns&#xff09;&#xff1a;2.3 行为型模式&#xff08;Behavioral Patterns&#xff09;&#xff1a; 3. 使用设计模式…