python日常记账本源代码,基于PySide6,支持快速查询、绘制图表

这篇具有很好参考价值的文章主要介绍了python日常记账本源代码,基于PySide6,支持快速查询、绘制图表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

python日常记账本源代码,基于PySide6(Qt for Python 6)的账本,界面简洁、功能强大,支持保存文件、快速查询、绘制图表等,是平时记账的不错选择。账目查询、账本编辑、添加/删除、撤销/重做、统计数据、生成图表。
运行截图:
python日常记账本源代码,基于PySide6,支持快速查询、绘制图表
python日常记账本源代码,基于PySide6,支持快速查询、绘制图表
python日常记账本源代码,基于PySide6,支持快速查询、绘制图表
python日常记账本源代码,基于PySide6,支持快速查询、绘制图表
完整程序下载地址:python日常记账本源代码
main.py

import sys
from bisect import insort_right
from functools import partial
from os.path import basename
from webbrowser import open_new_tab

from PySide6.QtWidgets import *
from PySide6.QtCore import Slot, QDate
from PySide6.QtGui import QStandardItem, QStandardItemModel

from api import ApiError, openFile, query, saveFile
from dlgAdd import dlgAdd
from dlgCharts import dlgCharts
from dlgSettings import dlgSettings
from ui_dlgHelp import Ui_Dialog as Ui_dlgHelp
from ui_MainWindow import Ui_MainWindow

# Version info
VERSION = '1.2.1'
CHANNEL = 'stable'
BUILD_DATE = '2022-08-25'
FULL_VERSION = f'{VERSION}-{CHANNEL} ({BUILD_DATE}) on {sys.platform}'

app = QApplication(sys.argv)

class AccountBookMainWindow(QMainWindow):
    version_str = '账本 ' + VERSION
    unsaved_tip = '*'
    SUPPORTED_FILTERS = '账本文件(*.abf);;文本文件(*.txt);;所有文件(*.*)'

    def __init__(self, parent=None):
        # Initialize window
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle('账本 ' + VERSION)
        self.labStatus = QLabel(self)
        self.ui.statusBar.addWidget(self.labStatus)

        # Initialize table
        self.model = QStandardItemModel(0, 4, self)
        self.model.setHorizontalHeaderLabels(['日期', '事项', '金额', '备注'])
        self.ui.table.setModel(self.model)
        self.ui.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        self.__data = []
        self.on_actFile_New_triggered()
        self.ui.actEdit_Remove.setEnabled(False)

        # Connect slots
        self.ui.table.selectionModel().selectionChanged.connect(self.__selectionChanged)
        self.model.itemChanged.connect(self.__itemChanged)

    def __updateTable(self, data):
        self.model.itemChanged.disconnect(self.__itemChanged)
        self.model.setRowCount(len(data))
        for row in range(len(data)):
            for col in range(len(data[row])):
                self.model.setItem(row, col, QStandardItem(data[row][col]))
        self.model.itemChanged.connect(self.__itemChanged)

    def __openFile(self, filename):
        try:
            self.__data = openFile(filename)
        except IOError:
            QMessageBox.critical(self, '错误', '文件打开失败。请稍后再试。')
        except ApiError:
            QMessageBox.critical(self, '错误', '文件格式错误。请检查文件完整性。')
        except Exception as e:
            QMessageBox.critical(self, '错误', '未知错误:' + str(e.with_traceback()))
        else:
            self.ui.searchEdit.clear()
            self.__key = ''
            self.__updateTable(self.__data)
            self.labStatus.setText(filename)
            self.setWindowTitle(self.version_str)
            self.__filename = filename

    def __saveFile(self, filename):
        try:
            saveFile(filename, self.__data)
        except IOError:
            QMessageBox.critical(self, '错误', '文件保存错误。请稍后再试。')
        except Exception as e:
            QMessageBox.critical(self, '错误', '未知错误:' + str(e.with_traceback()))
        else:
            self.labStatus.setText('保存成功:' + filename)
            self.setWindowTitle(self.version_str)
            self.__filename = filename

    @Slot()
    def on_actFile_New_triggered(self):
        self.__filename = self.__key = ''
        self.setWindowTitle(self.unsaved_tip + self.version_str)
        self.labStatus.setText('新文件')
        self.model.setRowCount(0)
        self.__data.clear()

    @Slot()
    def on_actFile_Open_triggered(self):
        filename, _ = QFileDialog.getOpenFileName(self, '打开', filter=self.SUPPORTED_FILTERS)
        if filename:
            self.__openFile(filename)

    @Slot()
    def on_actFile_Save_triggered(self):
        if self.__filename:
            self.__saveFile(self.__filename)
        else:
            filename, _ = QFileDialog.getSaveFileName(self, '保存', filter=self.SUPPORTED_FILTERS)
            if filename:
                self.__saveFile(filename)

    @Slot()
    def on_actFile_SaveAs_triggered(self):
        filename, _ = QFileDialog.getSaveFileName(self, '另存为', filter=self.SUPPORTED_FILTERS)
        if filename:
            self.__saveFile(filename)

    @Slot()
    def on_actFile_Settings_triggered(self):
        dlgSettings(self).exec()

    @Slot()
    def on_actHelp_About_triggered(self):
        dialog = QDialog(self)
        ui = Ui_dlgHelp()
        ui.setupUi(dialog)
        for link in (ui.githubLink, ui.giteeLink, ui.licenseLink, ui.readmeLink):
            link.clicked.connect(partial(open_new_tab, link.description()))
        ui.labVersion.setText('版本号:' + FULL_VERSION)
        ui.btnUpdate.clicked.connect(partial(open_new_tab, 'https://github.com/GoodCoder666/AccountBook/releases'))
        dialog.exec()

    @Slot()
    def on_actHelp_AboutQt_triggered(self):
        QMessageBox.aboutQt(self, '关于Qt')

    @Slot()
    def on_actEdit_Add_triggered(self):
        dialog = dlgAdd(self)
        if dialog.exec() == QDialog.Accepted:
            row = dialog.getRow()
            insort_right(self.__data, row)
            self.__updateTable(query(self.__data, self.__key))
            self.setWindowTitle(self.unsaved_tip + self.version_str)

    @Slot()
    def on_actEdit_Remove_triggered(self):
        rows = list(set(map(lambda idx: idx.row(), self.ui.table.selectedIndexes())))
        for row in rows:
            self.__data.remove([self.model.item(row, col).text() for col in range(self.model.columnCount())])
        self.model.itemChanged.disconnect(self.__itemChanged)
        self.model.removeRows(rows[0], len(rows))
        self.model.itemChanged.connect(self.__itemChanged)
        self.setWindowTitle(self.unsaved_tip + self.version_str)

    def __selectionChanged(self):
        self.ui.actEdit_Remove.setEnabled(self.ui.table.selectionModel().hasSelection())

    def __itemChanged(self, item: QStandardItem):
        i, j, new = item.row(), item.column(), item.text()
        if (old := self.__data[i][j]) == new: return
        if j == 0 and not QDate.fromString(new, 'yyyy/MM/dd').isValid():
            QMessageBox.critical(self, '错误', '日期格式错误。')
            self.model.itemChanged.disconnect(self.__itemChanged)
            item.setText(old)
            self.model.itemChanged.connect(self.__itemChanged)
            return
        row = self.__data.pop(i)
        row[j] = new
        insort_right(self.__data, row)
        self.__updateTable(query(self.__data, self.__key))
        self.setWindowTitle(self.unsaved_tip + self.version_str)

    @Slot()
    def on_searchEdit_textChanged(self):
        self.__key = self.ui.searchEdit.text()
        self.__updateTable(query(self.__data, self.__key))

    @Slot()
    def on_actStat_Show_triggered(self):
        if self.__data:
            dlgCharts(self.__data, self).exec()
        else:
            QMessageBox.information(self, '提示', '请添加数据以使用统计功能。')

    def closeEvent(self, event):
        if not self.windowTitle().startswith(self.unsaved_tip): return
        filename = basename(self.__filename) if self.__filename else '新文件'
        messageBox = QMessageBox(
            parent=self, icon=QMessageBox.Warning, windowTitle='提示',
            text=f'是否要保存对 {filename} 的更改?', informativeText='如果不保存,你的更改将丢失。',
            standardButtons=QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel
        )
        messageBox.setButtonText(QMessageBox.Save, '保存')
        messageBox.setButtonText(QMessageBox.Discard, '不保存')
        messageBox.setButtonText(QMessageBox.Cancel, '取消')
        reply = messageBox.exec()
        if reply == QMessageBox.Save:
            self.on_actFile_Save_triggered()
            event.accept()
        elif reply == QMessageBox.Discard:
            event.accept()
        else:
            event.ignore()

    def dragEnterEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        self.__openFile(event.mimeData().text()[8:]) # [8:] is to get rid of 'file:///'

mainform = AccountBookMainWindow()
mainform.show()

sys.exit(app.exec())

完整程序下载地址:python日常记账本源代码文章来源地址https://www.toymoban.com/news/detail-501776.html

到了这里,关于python日常记账本源代码,基于PySide6,支持快速查询、绘制图表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的生活垃圾检测与分类系统(Python+PySide6界面+训练代码)

    摘要:本篇博客详细讲述了如何利用深度学习构建一个生活垃圾检测与分类系统,并且提供了完整的实现代码。该系统基于强大的YOLOv8算法,并进行了与前代算法YOLOv7、YOLOv6、YOLOv5的细致对比,展示了其在图像、视频、实时视频流和批量文件处理中识别生活垃圾的准确性。文

    2024年04月29日
    浏览(41)
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的玉米病虫害检测系统(Python+PySide6界面+训练代码)

    摘要:本文介绍了一种基于深度学习的玉米病虫害检测系统系统的代码,采用最先进的YOLOv8算法并对比YOLOv7、YOLOv6、YOLOv5等算法的结果·,能够准确识别图像、视频、实时视频流以及批量文件中的玉米病虫害。文章详细解释了YOLOv8算法的原理,并提供了相应的Python实现代码、

    2024年02月22日
    浏览(54)
  • Python Qt PySide6简介

    自今天起开学学习教程,有网页介绍,有视频,非常的详细。 现将主要内容摘录如下: (结合自己的实际情况,略有增删和变动)(采用边实践边写的模式) 如果用  Python  语言开发  跨平台  的图形界面的程序,主要有3种选择: Tkinter 基于Tk的Python库,这是Python官方采用

    2024年02月14日
    浏览(48)
  • Python项目——搞怪小程序(PySide6+Pyinstaller)

    1、介绍 使用python编写一个小程序,回答你是猪吗。 点击“是”提交,弹窗并退出。 点击“不是”提交,等待5秒,重新选择。 并且隐藏了关闭按钮。 2、实现 新建一个项目。 2.1、设计UI 使用Qt designer设计一个UI界面,保存ui文件,再转换为py文件并保存到项目目录中,供后续

    2024年01月22日
    浏览(45)
  • Python GUI框架---- PySide6安装与使用 - 打包部署

    安装Python和PySide6 :首先,确保已经安装了Python和PySide6 。你可以从Python官方网站(https://www.python.org)下载并安装Python,然后使用pip命令安装PySide6 。 设计GUI界面:使用Qt Designer工具来设计GUI界面。Qt Designer是一个可视化的界面设计工具,可以帮助你创建和布局GUI界面。你可以

    2024年04月09日
    浏览(48)
  • Python项目——久坐提醒定时器(PySide6)编写

    1、介绍 使用Python编写一个久坐提醒软件。 功能: 设置工作时间。 设置休息时间。 选择休息时是否播放音乐。 休息时,软件置顶,且不能关闭。 2、工具 语言:python3.11 UI设计工具:Qt designer 编译器:PyCharm 包:pygame、PySide6 3、代码 新建一个项目,准备好音乐。 使用Qt des

    2024年01月19日
    浏览(49)
  • 【Python GUI编程系列 01】安装python pycharm 和 pyside6

    本系列使用 python3 + pycharm + pyside6 来进行python gui设计,首先我们来配置编程环境 PS:为了减少复杂程度,本文使用venv来创建虚拟环境,所有的包都安装在同一虚拟环境中,新手也可以不用虚拟环境直接安装,关于虚拟环境配置这部分 本系列不做过多介绍,感兴趣的同学可以

    2024年02月10日
    浏览(53)
  • 基于深度学习的高精度浣熊检测识别系统(PyTorch+Pyside6+模型)

    摘要:基于深度学习的高精度浣熊检测(水牛、犀牛、斑马和大象)识别系统可用于日常生活中或野外来检测与定位浣熊目标,利用深度学习算法可实现图片、视频、摄像头等方式的浣熊目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标

    2024年02月09日
    浏览(50)
  • Python+PySide6之模型/视图/委托框架QListView案例实践

    Qt中的模型/视图/委托框架是一种数据与可视化相互分离的技术,起源于Smalltalk的设计模式——Mode/View/Controller(MVC,模型/视图/控制器),通常在构建用户界面时使用。 MVC是由3部分组成。Model是应用程序对象,View是它的界面展示,Controller定义了界面对用户输入的反应方式。 Q

    2024年02月21日
    浏览(40)
  • 基于深度学习的CCPD车牌检测系统(PyTorch+Pyside6+YOLOv5模型)

    摘要:基于CCPD数据集的高精度车牌检测系统可用于日常生活中检测与定位车牌目标,利用深度学习算法可实现图片、视频、摄像头等方式的车牌目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集,使用Pysdie6库来搭建

    2024年02月14日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包