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

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

文章目录

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

效果图

请添加图片描述

概述

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

  • 框架:数据模型使用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.kler.cn/a/509328.html

相关文章:

  • macOS Sequoia 15.3 beta3(24D5055b)发布,附黑、白苹果镜像下载地址
  • Pytorch|YOLO
  • OpenAI函数调用迎来重大升级:引入「最小惊讶原则」等软件工程实践,开发体验更上一层楼!
  • 记录 idea 启动 tomcat 控制台输出乱码问题解决
  • 【MySQL】数据库约束和多表查询
  • 采用海豚调度器+Doris开发数仓保姆级教程(满满是踩坑干货细节,持续更新)
  • github登录用的TOTP和恢复码都丢失了怎么办
  • linux m、mm、mmm函数和make的区别
  • 与“神”对话:Swift 语言在 2025 中的云霓之望
  • Qt的核心机制概述
  • Google Titans: 测试阶段的学习与记忆
  • OLED--软件I2C驱动__标准库和HAL库
  • Windows 上安装 MongoDB 的 zip 包
  • Git简介
  • Rust 强制类型转换和动态指针类型的转换
  • Springboot的自动装配原理
  • 第23篇 基于ARM A9处理器用汇编语言实现中断<五>
  • 麒麟系统中删除权限不够的文件方法
  • 什么是 OpenResty
  • python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测
  • springboot基于微信小程序的智慧小区管理系统
  • 基于SSM实现的乡村振兴文化平台系统功能实现六
  • PyTorch使用教程(2)-torch包
  • C# 多线程 Task TPL任务并行
  • 七大设计原则之里氏替换原则
  • 2025西湖论剑-babytrace