基于QT模型/视图架构,零复杂SQL实现数据库数据可视化展示
一、核心知识点前置
1. 关键类作用
| 类名 | 核心作用 |
|---|---|
| QSqlTableModel | QT数据库模型类,直接映射SQLite3数据表,自动处理数据查询、缓存,无需手动编写SQL查询语句,为视图提供统一数据接口 |
| QTableView | QT视图层控件,将模型中的数据以表格形式渲染展示,支持列宽自适应、表头显示、数据选中等原生功能 |
| QSqlDatabase | QT数据库连接核心类,建立、管理与SQLite3的连接,是所有数据库操作的基础 |
2. 核心优势
- 无需编写
SELECT * FROM 表名等SQL查询语句,直接通过表名绑定数据,开发效率提升50%+ - 遵循模型/视图(MVC)架构,模型与视图分离,数据更新自动同步到界面
- 原生支持排序、筛选、分页功能,无需额外开发
- 可灵活配置编辑策略,快速实现数据的增删改查,兼顾展示与编辑需求
二、开发环境准备
1. 编译环境配置(.pro工程文件)
QT操作数据库必须依赖sql模块,需在工程.pro文件中显式添加,同时基础界面开发依赖widgets模块(QT5及以上版本)。
QT += core gui sql widgets # 核心:添加sql模块,缺一不可 TARGET = SqliteTableViewDemo # 自定义工程名 TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui
注意:添加模块后,必须重新执行qmake(QT Creator中:右键工程→执行qmake),否则会出现头文件找不到、函数未定义等编译错误。
2. 核心头文件引入
在需要操作数据库的源文件(如mainwindow.cpp、mainwindow.h)中,引入以下核心头文件,覆盖数据库连接、模型、视图、错误处理全流程:
// 数据库核心头文件 #include <QSqlDatabase> // 数据库连接管理 #include <QSqlTableModel> // 数据表模型(核心) #include <QSqlError> // 数据库错误信息(必加,用于调试) // 视图及辅助头文件 #include <QTableView> // 表格视图控件 #include <QHeaderView> // 表格表头配置(列宽自适应等)
三、SQLite3数据库准备
SQLite3是轻量级文件型数据库,无需独立的数据库服务,一个.db文件就是一个完整的数据库,准备步骤简单:
1. 数据库文件要求
- 准备一个有效的SQLite3数据库文件(如
mydata.db) - 数据库中创建可展示的数据表(如
student),并插入测试数据
2. 测试数据表创建(可选)
若无线程数据库,可通过SQLite3命令行、Navicat、SQLiteStudio等工具创建student表,以下是创表和插入测试数据的SQL语句:
-- SQLite3 创表语句(student表:学生信息) CREATE TABLE IF NOT EXISTS student ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- 自增ID,主键 name TEXT NOT NULL, -- 姓名 age INTEGER, -- 年龄 score REAL -- 分数 ); -- 插入测试数据 INSERT INTO student (name, age, score) VALUES ('张三', 18, 95.5), ('李四', 19, 88.0), ('王五', 18, 92.5), ('赵六', 20, 90.0);小技巧:将创建好的mydata.db文件放到QT工程的可执行文件目录(如build-xxx-Release/release、build-xxx-Debug/debug),程序可直接通过文件名访问,无需写绝对路径。
四、完整代码实现(分步讲解)
以QT Widgets工程为例,主界面为MainWindow,界面中放置一个QTableView控件(ui->tableView),核心流程分为3步:建立数据库连接 → 初始化QSqlTableModel模型 → 模型与TableView绑定,全程附带错误处理,保证程序健壮性。
步骤1:MainWindow头文件(mainwindow.h)
声明基础窗口类,可选将模型声明为成员变量,方便后续扩展(如筛选、编辑):
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> // 提前引入核心头文件,避免源文件重复引入 #include <QSqlDatabase> #include <QSqlTableModel> #include <QSqlError> #include <QTableView> #include <QHeaderView> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; QSqlTableModel *m_sqlModel; // 数据表模型,作为成员变量方便扩展 }; #endif // MAINWINDOW_H步骤2:源文件核心实现(mainwindow.cpp)
核心逻辑均在构造函数中,包含数据库连接校验、模型初始化、视图美化配置,每一步操作都做结果判断,错误时弹出提示框:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> // 用于弹出错误提示框 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_sqlModel(nullptr) // 初始化模型指针,避免野指针 { ui->setupUi(this); this->setWindowTitle("QSqlTableModel+SQLite3 数据展示"); /********************* 第一步:建立SQLite3数据库连接 *********************/ // 1. 指定数据库驱动:SQLite3对应的驱动名为"QSQLITE"(QT内置,无需额外安装) QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); // 2. 设置数据库文件名:相对路径(可执行文件目录)或绝对路径(如"D:/data/mydata.db") db.setDatabaseName("mydata.db"); // 3. 打开数据库并校验连接结果 if (!db.open()) { // 连接失败:通过lastError()获取详细错误信息,弹窗提示 QMessageBox::critical(this, "数据库连接失败", "错误信息:" + db.lastError().text(), QMessageBox::Ok); return; // 连接失败,后续操作无意义,直接返回 } /********************* 第二步:初始化QSqlTableModel模型 *********************/ // 1. 创建模型对象,父对象设为窗口(利用QT父子机制自动释放内存,避免内存泄漏) m_sqlModel = new QSqlTableModel(this); // 2. 绑定SQLite3中的数据表:设置要展示的表名(与数据库中一致) m_sqlModel->setTable("student"); // 3. 设置编辑策略:本文仅做展示,设为手动提交(只读效果) // 编辑策略说明:OnFieldChange(字段改即同步)、OnRowChange(行改后同步)、OnManualSubmit(手动提交) m_sqlModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // 4. 加载数据:select()等价于执行SELECT * FROM student,返回bool表示是否成功 if (!m_sqlModel->select()) { QMessageBox::critical(this, "数据加载失败", "错误信息:" + m_sqlModel->lastError().text(), QMessageBox::Ok); db.close(); // 加载失败,关闭数据库连接 return; } /********************* 第三步:模型与QTableView绑定并配置视图 *********************/ // 1. 核心操作:将模型设置到TableView,视图自动渲染数据 ui->tableView->setModel(m_sqlModel); // 2. 配置表头:列宽自适应窗口,最后一列拉伸填充剩余空间(提升界面体验) ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 3. 禁止表格编辑(双层保障:模型只读+视图只读) ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 4. 设置选中方式:整行选中(更符合用户操作习惯) ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 5. 隐藏垂直表头(行号),让界面更简洁(可选) // ui->tableView->verticalHeader()->setVisible(false); } MainWindow::~MainWindow() { // 析构时关闭数据库连接,释放资源 QSqlDatabase::database().close(); delete ui; }步骤3:主函数(main.cpp)
使用QT Widgets默认主函数即可,无需任何修改:
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }五、UI界面设计(极简操作)
无需复杂的UI配置,仅需3步完成TableView控件的放置,全程在QT Creator设计模式中操作:
- 打开QT Creator的设计模式(双击
mainwindow.ui文件); - 从左侧控件栏拖入一个
TableView控件到主窗口界面; - 右键主窗口空白处 → 选择布局 → 栅格布局,让TableView填充整个窗口,实现界面自适应。
提示:无需修改TableView的任何属性,所有配置均通过代码实现,便于后续维护和扩展。
六、编译运行与效果验证
1. 运行前必做检查
- 已为工程添加
sql模块并重新执行qmake; mydata.db文件已放到工程可执行文件目录;- 代码中
setTable("student")的表名与数据库中表名完全一致(区分大小写); - 数据表中已插入测试数据。
2. 预期运行效果
程序启动后,将直接在TableView中展示SQLite3数据库student表的所有数据,效果如下:
- 表头自动显示数据库表的字段名(id、name、age、score);
- 表格中完整展示所有测试数据行,无数据缺失;
- 拖动窗口大小时,表格列宽自动自适应,无滚动条冗余;
- 表格为只读状态,点击单元格无法编辑,避免误操作。
3. 常见错误排查
常见问题及解决方法:
- 数据库连接失败:检查
.db文件路径是否正确、文件是否损坏、程序是否有文件读写权限; - 数据加载失败:检查表名是否拼写错误、数据表是否存在于数据库中;
- 编译错误:忘记在
.pro文件中添加sql模块,重新添加并执行qmake; - 表格无数据:数据表中未插入测试数据,执行INSERT语句插入后重新运行程序;
- 表头乱码:QT工程编码设置为UTF-8(QT Creator:工具→选项→文本编辑器→编码)。
七、核心扩展功能(轻量实现)
基于基础代码,无需大幅修改,可快速实现常用扩展功能,满足实际开发中的多样化需求,所有代码均添加在m_sqlModel->select()之后、模型与视图绑定之前。
1. 自定义表头显示文本
默认表头显示数据库字段名(如id、name),可自定义为中文或其他友好名称,提升界面可读性:
// 自定义表头:第0列-编号,第1列-姓名,第2列-年龄,第3列-分数 m_sqlModel->setHeaderData(0, Qt::Horizontal, "编号"); m_sqlModel->setHeaderData(1, Qt::Horizontal, "姓名"); m_sqlModel->setHeaderData(2, Qt::Horizontal, "年龄"); m_sqlModel->setHeaderData(3, Qt::Horizontal, "分数");
2. 按条件筛选数据
无需编写WHERE语句,通过setFilter()实现数据筛选,参数为SQL筛选条件字符串:
// 筛选条件1:年龄大于18的学生 m_sqlModel->setFilter("age > 18"); // 筛选条件2:分数大于90且年龄等于18的学生 // m_sqlModel->setFilter("score > 90 AND age = 18"); // 筛选条件3:姓名包含"张"的学生(SQLite3模糊查询用LIKE) // m_sqlModel->setFilter("name LIKE '%张%'"); m_sqlModel->select(); // 重新加载数据,应用筛选条件3. 按列排序(升序/降序)
TableView默认支持点击表头排序,也可通过代码手动设置默认排序规则,指定排序列和排序方式:
// 按分数降序排序(第3列,Qt::DescendingOrder=降序,Qt::AscendingOrder=升序) m_sqlModel->setSort(3, Qt::DescendingOrder); // 按年龄升序排序 // m_sqlModel->setSort(2, Qt::AscendingOrder); m_sqlModel->select(); // 重新加载数据,应用排序规则
4. 开启数据编辑功能
若需要在TableView中直接编辑数据并同步到SQLite3数据库,只需修改2处配置,取消只读限制:
// 1. 修改模型编辑策略为「字段修改立即同步到数据库」 m_sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange); // 2. 注释或删除视图的只读设置代码 // ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
5. 隐藏指定列
若无需展示某些字段(如主键id),可通过TableView隐藏指定列,不影响数据库数据:
// 隐藏第0列(id列),数字为列的索引(从0开始) ui->tableView->setColumnHidden(0, true);
八、核心注意事项
- SQLite3驱动无需额外安装:QT内置
QSQLITE驱动,直接指定驱动名即可使用,无需配置第三方库; - 内存管理规范:将QSqlTableModel的父对象设为窗口,利用QT父子对象机制自动释放内存,避免野指针和内存泄漏;
- 数据库连接管理:一个工程中默认数据库连接名可省略,析构函数中通过
QSqlDatabase::database().close()统一关闭; - 编辑策略选择:批量修改数据时,推荐使用
OnManualSubmit(手动提交),修改完成后调用m_sqlModel->submitAll()提交,避免频繁操作数据库; - 绝对路径使用场景:若需要将数据库文件放在指定目录,使用绝对路径(如
D:/QT_Project/data/mydata.db),并保证目录存在; - 多表关联处理:QSqlTableModel仅支持单表操作,若需要多表关联查询,可使用
QSqlQueryModel配合自定义SQL语句。
九、总结
本文通过QSqlTableModel+QTableView实现了QT中SQLite3数据表的快速展示,核心是利用QT的模型/视图架构,将数据层与展示层分离,相比传统的QSqlQuery手动执行SQL、逐行填充表格的方式,该方案具有开发效率高、维护成本低、功能扩展性强的优势。
核心实现步骤可总结为3个关键节点:
- 工程配置:
.pro文件添加sql模块,引入核心头文件; - 核心流程:建立SQLite3连接 → 初始化模型并绑定数据表 → 模型与TableView绑定;
- 健壮性保障:所有数据库操作添加结果校验,通过
lastError()获取错误信息,方便调试。
在此基础上,可快速扩展筛选、排序、编辑、隐藏列等功能,满足大部分QT数据库可视化开发的基础需求,该方案不仅适用于SQLite3,稍作修改(仅修改数据库驱动和连接参数)即可适配MySQL、PostgreSQL等其他数据库,具有良好的通用性。
初始化的时候 只做
new QSqlTableModel(this);
然后再定时器中 执行
xxxx->setTable("chm_0x26"); // 设置表名xxxx->select(); // 执行查询,获取所有行
否则数据库内容变更了 不更新