优秀的编程知识分享平台

网站首页 > 技术文章 正文

Python GUI 编程入门教程 第35章:记账本应用升级——月度趋势图

nanyue 2025-09-21 20:11:58 技术文章 3 ℃

35.1 项目目标

  1. 新增 “导出月度趋势图” 功能
  2. 使用折线图展示 每个月的收入/支出变化
  3. 管理员可以查看所有用户的趋势,普通用户仅能查看自己的
  4. 支持导出为 PNG 图片,便于保存和分享

35.2 数据准备

我们需要把数据库里的日期字段(如 "2025-09-01") 转换为年月,再进行分组统计:

  • 收入趋势:每月总收入
  • 支出趋势:每月总支出

35.3 实现月度趋势图

在 BudgetApp 中新增:

import matplotlib.dates as mdates
import pandas as pd

class BudgetApp:
    # ... 前面代码省略

    def export_monthly_trend(self):
        """导出月度收支趋势图"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG 图片", "*.png")]
        )
        if not file_path:
            return

        # 获取数据
        if self.role == "user":
            self.cursor.execute("SELECT date, type, amount FROM records WHERE user_id=?", (self.user_id,))
        else:
            self.cursor.execute("SELECT date, type, amount FROM records")

        rows = self.cursor.fetchall()
        if not rows:
            messagebox.showwarning("提示", "没有数据可导出图表")
            return

        # 转换为 DataFrame 方便处理
        df = pd.DataFrame(rows, columns=["date", "type", "amount"])
        df["date"] = pd.to_datetime(df["date"])
        df["month"] = df["date"].dt.to_period("M")

        # 分组统计
        monthly = df.groupby(["month", "type"])["amount"].sum().unstack(fill_value=0)
        monthly = monthly.sort_index()

        # 绘制折线图
        fig, ax = plt.subplots(figsize=(8, 5))
        if "收入" in monthly:
            ax.plot(monthly.index.astype(str), monthly["收入"], marker="o", label="收入", color="#4caf50")
        if "支出" in monthly:
            ax.plot(monthly.index.astype(str), monthly["支出"], marker="o", label="支出", color="#f44336")

        ax.set_title("月度收支趋势")
        ax.set_xlabel("月份")
        ax.set_ylabel("金额")
        ax.legend()
        ax.grid(True)
        plt.xticks(rotation=45)

        plt.tight_layout()
        try:
            plt.savefig(file_path)
            plt.close(fig)
            messagebox.showinfo("成功", f"月度趋势图已导出到 {file_path}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {e}")

35.4 在界面中加入按钮

在 BudgetApp.__init__ 的操作按钮区增加:

tk.Button(frame_btn, text="导出月度趋势图", command=self.export_monthly_trend).pack(side=tk.LEFT, padx=10)

35.5 功能演示

  1. 用户点击 “导出月度趋势图”
  2. 程序读取所有账单记录,按月统计收入和支出
  3. 导出的 trend.png 图片内容:
  4. X 轴:月份(如 2025-06, 2025-07, 2025-08...)
  5. Y 轴:金额
  6. 绿色折线:收入
  7. 红色折线:支出
  8. 折线带点,清晰展示每月的变化趋势
  9. 普通用户:只显示自己数据
  10. 管理员:包含所有用户的总数据

35.6 小结

  • 使用 pandas 进行数据分组和统计
  • 使用 matplotlib 绘制折线图,展示趋势
  • 月度收支趋势图比单次报表更直观

Tags:

最近发表
标签列表