Qt记账系统源码编译与实战开发指南
2026/9/13 7:50:20 网站建设 项目流程

简介:这是一套基于Qt框架开发的轻量级记账系统完整源码,面向计算机、电子信息及数学类专业的本科生,适用于课程设计、期末大作业与毕业设计等实践教学场景,帮助学习者掌握C++ GUI应用开发的核心流程与数据管理逻辑。资源压缩包共12个文件,包含4个核心功能模块的.cpp实现文件、3个对应头文件(.h)定义类结构与接口、2个.ui界面文件可视化布局、1个.pro工程配置文件、1份README.md项目说明文档及1张运行效果截图(.jpg),整体仅32KB,结构精炼、便于快速编译运行。已有411人学习下载,读者可直接导入Qt Creator构建运行,获得从界面设计、信号槽连接、数据增删改查到本地文件持久化的全流程参考;代码模块划分清晰,add_scree、show_scree等命名体现功能边界,配合项目说明文档,为二次扩展与功能定制提供扎实基础。

1. 这不是又一个“Hello World”QT项目:它是一套可编译、可调试、可二次开发的记账系统完整工程

你下载了一个名为“基于QT编写的记账系统源码+项目说明.zip”的压缩包,解压后看到.pro文件、main.cppmainwindow.ui和一堆.h/.cpp,但双击xxx.pro打不开?用 Qt Creator 打开却报错Unknown module(s) in QT: widgets?或者编译通过了,运行时弹窗提示QApplication: No such file or directory?——这说明你面对的不是一个演示片段,而是一个真实落地的桌面级财务工具工程:它依赖 Qt Widgets 模块构建 UI,使用 SQLite 做本地持久化,包含账户管理、收支分类、流水录入、月度统计等完整业务闭环。它适合两类人:一是刚学完 Qt 基础想练手的真实项目(不是玩具计算器),二是需要快速搭建个人/小微团队记账工具的技术人员,直接复用其数据模型与界面结构,省去从零设计数据库表和信号槽绑定的时间。本篇不讲 Qt 安装步骤,而是聚焦于如何让这个 ZIP 包在你的机器上真正跑起来、改得动、扩得开——从环境校验到模块拆解,从编译排错到关键逻辑定位,全部基于你手头这份源码展开。

2. 环境校验与项目加载:先确认 Qt 版本兼容性,再解决 .pro 文件识别失败问题

2.1 验证本地 Qt 安装是否满足该项目最低要求

该记账系统源码极大概率基于 Qt 5.x 构建(Qt 6 对 Widgets 模块有重大 ABI 变更,且项目说明中未提及其适配)。需确认两点:一是 Qt 安装路径是否被系统识别,二是所选 Kit 是否启用widgets模块。执行以下命令验证:

# 查看已安装 Qt 版本(Linux/macOS) qmake -v # Windows 下在 Qt Creator 的 "Tools → Options → Kits → Qt Versions" 中确认

提示:若输出为QMake version 3.1Using Qt version 5.15.2,则版本匹配;若显示QMake version 4.0(对应 Qt 6.x),则需额外配置兼容层或降级安装 Qt 5.15.2。Qt 5.15 是最后一个提供长期支持(LTS)的 5.x 版本,也是当前开源记账类项目最广泛采用的基线。

2.2 解决 Qt Creator 无法加载 .pro 文件的三类典型原因

2.2.1 Kit 未正确关联 Qt 版本

打开 Qt Creator →Projects侧边栏 → 点击左下角Manage Kits...→ 在Qt Versions标签页确认已添加路径如/opt/Qt/5.15.2/gcc_64/bin/qmake(Linux)或C:\Qt\5.15.2\msvc2019_64\bin\qmake.exe(Windows)。若未出现,点击Add手动指定qmake路径。随后在Kits标签页,新建或编辑 Kit,将Qt version下拉框设为刚添加的 5.15.2 版本,并确保Compiler与之匹配(如 MSVC 2019 或 GCC 9.3+)。

2.2.2 .pro 文件缺失必要模块声明

用文本编辑器打开项目根目录下的.pro文件,检查是否包含以下行:

QT += core widgets gui sql TARGET = accountbook TEMPLATE = app SOURCES += main.cpp \ mainwindow.cpp \ databasehelper.cpp \ transactionmodel.cpp HEADERS += mainwindow.h \ databasehelper.h \ transactionmodel.h FORMS += mainwindow.ui

注意:QT += widgets gui sql是核心——widgets提供 QPushButton/QTableView 等控件,gui支持图标与字体渲染,sql启用 QSqlDatabase 接口。若缺失sql,编译时会报QSqlDatabase: No such file or directory;若仅写QT += core,则所有 UI 类均不可用。

2.2.3 项目说明文档中隐含的构建约束

查阅项目说明.txt(或 README.md),重点关注是否有类似以下描述:

  • “需使用 MSVC 2019 编译器构建” → Windows 用户必须在 Qt Creator 中选择Desktop Qt 5.15.2 MSVC2019 64-bitKit;
  • “SQLite 数据库文件位于data/account.db” → 首次运行前需手动创建data/目录,否则QSqlDatabase::addDatabase("QSQLITE")会因路径不存在而连接失败;
  • “图标资源使用resources.qrc” → 确认.pro文件中存在RESOURCES += resources.qrc,且resources.qrc<file>icons/add.png</file>路径与实际文件位置一致。

2.3 执行一次干净的构建流程:从 qmake 到可执行文件

完成上述配置后,在 Qt Creator 中执行:

  1. Build → Clean All清除旧构建产物;
  2. Build → Run qmake强制重新解析.pro并生成 Makefile;
  3. Build → Build Project编译;
  4. 若编译成功,在build-xxx-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug目录下找到accountbook.exe(Windows)或accountbook(Linux/macOS)。

注意:若链接阶段报错LNK2019: unresolved external symbol,大概率是某个.cpp文件未在.proSOURCES列表中声明,或头文件中声明了函数但未在对应.cpp中实现。此时需比对项目说明中的模块列表与实际文件名是否完全一致。

3. 核心模块解析:从数据库初始化到收支流水展示的四层代码链路

3.1 DatabaseHelper:封装 SQLite 初始化与表结构定义

该类通常位于databasehelper.h/cpp,承担项目数据底座职责。其关键逻辑在于initDatabase()方法:

bool DatabaseHelper::initDatabase() { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("data/account.db"); // 注意:路径需存在,否则 open() 失败 if (!db.open()) { qWarning() << "Cannot open database:" << db.lastError().text(); return false; } // 创建账户表 QSqlQuery query(db); query.exec("CREATE TABLE IF NOT EXISTS accounts (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "name TEXT NOT NULL, " "balance REAL DEFAULT 0.0)"); // 创建交易流水表(关键:外键关联 accounts.id) query.exec("CREATE TABLE IF NOT EXISTS transactions (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "account_id INTEGER NOT NULL, " "type TEXT CHECK(type IN ('income','expense')), " "amount REAL NOT NULL, " "category TEXT, " "note TEXT, " "date DATE DEFAULT (date('now')), " "FOREIGN KEY(account_id) REFERENCES accounts(id))"); return true; }

逻辑说明:QSqlDatabase::addDatabase("QSQLITE")注册 SQLite 驱动;db.setDatabaseName()设置物理文件路径;query.exec()执行 DDL 语句。此处FOREIGN KEY约束确保每笔交易必属某个账户,避免数据孤岛。参数说明:type TEXT CHECK(...)限制取值为 income/expense,比枚举类型更轻量且跨平台兼容。

3.2 TransactionModel:继承 QStandardItemModel 实现表格数据绑定

该模型类负责将transactions表数据映射到QTableView。其loadData()方法体现 Qt Model/View 架构精髓:

void TransactionModel::loadData() { this->clear(); // 清空现有项 QSqlQuery query("SELECT t.id, a.name, t.type, t.amount, t.category, t.note, t.date " "FROM transactions t JOIN accounts a ON t.account_id = a.id " "ORDER BY t.date DESC"); while (query.next()) { QList<QStandardItem*> row; row << new QStandardItem(query.value(0).toString()); // id row << new QStandardItem(query.value(1).toString()); // account name row << new QStandardItem(query.value(2).toString()); // type row << new QStandardItem(QString::number(query.value(3).toDouble(), 'f', 2)); // amount, 保留2位小数 row << new QStandardItem(query.value(4).toString()); // category row << new QStandardItem(query.value(5).toString()); // note row << new QStandardItem(query.value(6).toString()); // date this->appendRow(row); } }

参数说明:QString::number(value, 'f', 2)将浮点数格式化为固定小数位字符串,避免金额显示为100.000000JOIN accounts a ON t.account_id = a.id实现账户名称内联查询,省去前端拼接逻辑;ORDER BY t.date DESC确保最新交易排在表格顶部,符合记账习惯。

3.3 MainWindow:信号槽驱动的业务逻辑中枢

主窗口类通过connect()绑定 UI 控件事件与数据操作。关键信号连接如下:

// 连接“新增交易”按钮点击信号 connect(ui->btnAddTransaction, &QPushButton::clicked, this, &MainWindow::onAddTransactionClicked); // 连接表格双击编辑信号 connect(ui->tableView, &QTableView::doubleClicked, this, &MainWindow::onTransactionDoubleClicked); // 连接日期选择器变更信号(用于筛选) connect(ui->dateFrom, &QDateEdit::dateChanged, this, &MainWindow::onDateRangeChanged); connect(ui->dateTo, &QDateEdit::dateChanged, this, &MainWindow::onDateRangeChanged);

逻辑说明:onAddTransactionClicked()会弹出AddTransactionDialog对话框,收集用户输入后调用DatabaseHelper::insertTransaction()写入数据库;onTransactionDoubleClicked()获取当前行索引,提取id字段启动编辑流程;onDateRangeChanged()触发TransactionModel::filterByDate()方法,动态刷新表格内容。这种松耦合设计使 UI 与数据层完全解耦。

3.4 AddTransactionDialog:模态对话框实现表单验证与提交

该对话框类(通常为addtransactiondialog.h/cpp)包含QComboBox(账户选择)、QComboBox(类别选择)、QDoubleSpinBox(金额)、QTextEdit(备注)等控件。其accept()重载方法执行提交前验证:

void AddTransactionDialog::accept() { if (ui->cmbAccount->currentText().isEmpty()) { QMessageBox::warning(this, "输入错误", "请选择账户!"); return; } if (ui->spinAmount->value() <= 0) { QMessageBox::warning(this, "输入错误", "金额必须大于零!"); return; } // 构造交易数据并提交 TransactionData data; data.accountId = getAccountIdByName(ui->cmbAccount->currentText()); data.type = ui->cmbType->currentText() == "收入" ? "income" : "expense"; data.amount = ui->spinAmount->value(); data.category = ui->cmbCategory->currentText(); data.note = ui->txtNote->toPlainText(); data.date = ui->dateEdit->date().toString("yyyy-MM-dd"); if (dbHelper->insertTransaction(data)) { QDialog::accept(); // 关闭对话框 } else { QMessageBox::critical(this, "保存失败", "数据库写入异常,请检查日志"); } }

参数说明:getAccountIdByName()通过QSqlQuery查询accounts表获取 ID,避免前端硬编码;ui->spinAmount->value()直接读取控件数值,无需字符串转换;QDialog::accept()是标准关闭方式,触发exec()返回QDialog::Accepted,使主窗口能感知提交成功。

4. 功能扩展实战:为记账系统增加月度统计图表与导出 Excel 功能

4.1 使用 Qt Charts 绘制收支趋势折线图

Qt Charts 是 Qt 官方提供的可视化模块,需在.pro中追加:

QT += charts

mainwindow.h中添加:

#include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include <QtCharts/QValueAxis>

MainWindow::setupMonthlyChart()中构建图表:

void MainWindow::setupMonthlyChart() { QChart *chart = new QChart(); chart->setTitle("月度收支趋势(近6个月)"); QLineSeries *incomeSeries = new QLineSeries(); QLineSeries *expenseSeries = new QLineSeries(); incomeSeries->setName("收入"); expenseSeries->setName("支出"); // 查询近6个月数据(SQLite 日期函数) QSqlQuery query; query.exec("SELECT strftime('%Y-%m', date) as month, " "SUM(CASE WHEN type='income' THEN amount ELSE 0 END) as income_total, " "SUM(CASE WHEN type='expense' THEN amount ELSE 0 END) as expense_total " "FROM transactions " "WHERE date >= date('now', '-6 months') " "GROUP BY month ORDER BY month"); while (query.next()) { QString month = query.value(0).toString(); qreal income = query.value(1).toDouble(); qreal expense = query.value(2).toDouble(); incomeSeries->append(month.toLongLong(), income); // X轴用时间戳,Y轴为金额 expenseSeries->append(month.toLongLong(), expense); } chart->addSeries(incomeSeries); chart->addSeries(expenseSeries); QValueAxis *axisX = new QValueAxis(); axisX->setTitleText("月份"); chart->setAxisX(axisX, incomeSeries); chart->setAxisX(axisX, expenseSeries); QValueAxis *axisY = new QValueAxis(); axisY->setTitleText("金额(元)"); chart->setAxisY(axisY, incomeSeries); chart->setAxisY(axisY, expenseSeries); QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); ui->chartContainer->layout()->addWidget(chartView); // 假设 UI 中有 QVBoxLayout 名为 chartContainer }

注意:strftime('%Y-%m', date)提取年月字符串,CASE WHEN实现条件聚合,这是 SQLite 原生支持的高效统计方式,无需在 Qt 层遍历数据。chart->setAxisX()必须为每个 Series 显式绑定坐标轴,否则图表不显示。

4.2 导出当前表格数据为 Excel 文件(使用 QXlsx 库)

Qt 原生不支持 Excel,需引入第三方库 QXlsx 。下载xlsxwriter分支源码,将其src目录复制到项目3rdparty/qxlsx/,并在.pro中添加:

INCLUDEPATH += $$PWD/3rdparty/qxlsx DEPENDPATH += $$PWD/3rdparty/qxlsx SOURCES += $$PWD/3rdparty/qxlsx/xlsxdocument.cpp \ $$PWD/3rdparty/qxlsx/xlsxformat.cpp \ $$PWD/3rdparty/qxlsx/xlsxcell.cpp HEADERS += $$PWD/3rdparty/qxlsx/xlsxdocument.h \ $$PWD/3rdparty/qxlsx/xlsxformat.h \ $$PWD/3rdparty/qxlsx/xlsxcell.h

MainWindow::exportToExcel()中实现导出:

void MainWindow::exportToExcel() { QXlsx::Document xlsx; xlsx.addSheet("收支明细"); // 写入表头 QStringList headers = {"ID", "账户", "类型", "金额", "类别", "备注", "日期"}; for (int i = 0; i < headers.size(); ++i) { xlsx.write(1, i + 1, headers[i]); // 行列从1开始 } // 写入表格数据(从 model 中逐行读取) for (int row = 0; row < model->rowCount(); ++row) { for (int col = 0; col < model->columnCount(); ++col) { QString value = model->index(row, col).data(Qt::DisplayRole).toString(); xlsx.write(row + 2, col + 1, value); // 第2行开始写数据 } } QString fileName = QFileDialog::getSaveFileName(this, "导出Excel", "", "Excel Files (*.xlsx)"); if (!fileName.isEmpty()) { if (!fileName.endsWith(".xlsx")) fileName += ".xlsx"; if (xlsx.saveAs(fileName)) { QMessageBox::information(this, "导出成功", QString("已导出 %1 条记录到 %2").arg(model->rowCount()).arg(fileName)); } else { QMessageBox::critical(this, "导出失败", "文件写入错误"); } } }

提示:QXlsx::Document是纯内存操作,不依赖 Office 组件;xlsx.write(row, col, value)的行列索引从1开始,与 Excel 表格一致;model->index(row, col).data(Qt::DisplayRole)获取视图显示文本,而非原始数据,确保导出内容与用户所见完全一致。

5. 调试与发布:定位常见崩溃点及生成可分发的独立程序包

5.1 三类高频崩溃场景的定位与修复方法

崩溃现象日志线索定位手段修复方案
启动即崩溃,无任何窗口QApplication: No such file or directory检查main.cpp是否包含#include <QApplication>QApplication a(argc, argv);是否在main()函数首行确认QT += core gui widgets已在.pro中声明,且main.cpp头文件包含顺序正确(先#include <QApplication>,再#include "mainwindow.h"
点击按钮后程序退出Segmentation fault (core dumped)在 Qt Creator 中启用Run → Start Debugging,崩溃时查看Locals窗口,观察指针是否为nullptr检查ui->xxx控件是否在ui->setupUi(this)后才被访问;确认QSqlQuery对象是否在QSqlDatabase有效连接状态下创建
表格显示空白但无报错QSqlQuery::exec: database not openTransactionModel::loadData()开头添加qDebug() << "DB open?" << db.isOpen();DatabaseHelper::initDatabase()成功后,确保QSqlDatabase::database()返回的实例被全局复用,而非每次新建QSqlQuery时都调用QSqlDatabase::addDatabase()

5.2 使用 windeployqt(Windows)或 macdeployqt(macOS)打包可执行文件

Windows 下生成绿色免安装包

在 Qt 安装目录的bin子目录中找到windeployqt.exe(如C:\Qt\5.15.2\msvc2019_64\bin\windeployqt.exe),执行:

# 假设可执行文件在 build 目录下 cd /path/to/build-xxx-Desktop_Qt_5_15_2_MSVC2019_64bit-Release windeployqt --no-compiler-runtime --no-system-d3d-compiler --release accountbook.exe

参数说明:--no-compiler-runtime排除 MSVC 运行时(需用户自行安装 VC++ Redistributable);--no-system-d3d-compiler避免复制系统级 d3dcompiler_47.dll;--release指定发布模式。执行后,accountbook.exe同目录将生成platforms/qwindows.dllplugins/imageformats/qjpeg.dll等必要插件。

macOS 下处理 Framework 依赖
# 先确认 Qt 安装路径 export PATH="/Users/xxx/Qt/5.15.2/clang_64/bin:$PATH" macdeployqt accountbook.app -dmg -verbose=2

注意:macdeployqt会自动将 Qt Frameworks 拷贝进.app/Contents/Frameworks/,并修正@rpath。若仍提示Library not loaded: @rpath/...,需用otool -L accountbook.app/Contents/MacOS/accountbook查看缺失库,再用install_name_tool -change修正路径。

5.3 为 Linux 用户提供 AppImage 打包方案(兼容主流发行版)

AppImage 是 Linux 下最接近“绿色软件”的分发格式。使用linuxdeployqt工具:

# 下载 linuxdeployqt-x86_64.AppImage chmod +x linuxdeployqt-x86_64.AppImage ./linuxdeployqt-x86_64.AppImage accountbook.desktop -appimage

其中accountbook.desktop内容为:

[Desktop Entry] Name=记账系统 Exec=accountbook Icon=accountbook Type=Application Categories=Utility;Finance;

提示:linuxdeployqt会自动检测accountbook依赖的.so库(如libQt5Widgets.so.5),将其打包进 AppImage 内部,并生成启动脚本。用户双击即可运行,无需安装 Qt 环境。

直接将accountbook-x86_64.AppImage文件分发给 Ubuntu 20.04、CentOS 7、Debian 11 等系统用户,他们无需关心 Qt 版本或库路径,打开即用。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询