使用Deepseek创建「学习时间记录」程序

# Deepseek 身份命令
你是一名代码大师,熟知Python ,Java等语言编写,精通制作各种程序,并能熟练找出别人代码的问题进行修改和优化。
# 程序设定命令
制作一款Python程序,项目有三种(主动学习\被动学习\创作)每个项目分别匹配一个icon,制作成三个正方形圆角按钮,选中后变色,同时间阶段只能选择一个。
功能:
1. 正常记录:用户先选择一个项目(主动学习),点击开始,记录开始时间(eg: 2025-4-16,18:55);用户点击结束,记录结束时间(eg: 2025-4-16,19:55),保存记录(2025-4-16,主动学习 60min,18:55-19:55)
2.增加一个手动调整按钮,可以手动输入:选中项:三个正方形圆角按钮项目(主动学习\被动学习\创作)只能选一个,填入项: 日期(yyyy,mm,dd)、开始时间、结束时间。
3.笔记本(设置成按钮,点击后弹出界面):包含所有记录(「正常记录」和「手动调整」),保存记录样式(单条显示样式:2025-4-16,主动学习 60min,18:55-19:55)可双击某条进行编辑修改,可单击某条选中,右键显示删除选项,将某条删除。
4.折线图(设置成按钮,点击后弹出界面):横轴为日期(eg:2025-04-15),纵轴为当天记录总时长(eg: 95min),横轴纵轴不显示文字,当鼠标悬停在点上时,显示对应信息(eg:2025-04-15, 95min)「折线图」数据从「笔记本」中提取。
请修正完善程序逻辑,并制作具有如上功能的python程序,输出完整代码。

【Deepseek输出 V1.0代码】

#根据V1.0代码提出修改命令
修改:
1. 项目有三种(主动学习\被动学习\创作)每个项目分别匹配一个icon不显示文字,制作成三个正方形圆角按钮。icon调用地址:C:\Users\XXX
「主动学习」icon名:active_learning.jpg,「被动学习」icon名:passive_learning.jpg,「创作」icon名:creative.jpg
2. 当选中项目,点击「开始记录」:界面显示开始时间,并显示计时,直到点击「结束记录」,显示结束时间,锁定计时。
3. 「手动调整」「笔记本」「折线图」三个按钮并列排布
4.目前项目存在问题:「手动调整」「笔记本」「折线图」这三个按钮点击后未弹出界面,无法调用。
请修正上述问题,发送修改后的完整代码

【Deepseek输出V2.0代码】运行出错

#将出错的代码程序复制粘贴发给Deepseek

【Deepseek输出V3.0代码】此时输出非完全代码,会简略部分不需更改的代码,但自行修改后出现错误

#这是修改后的代码:****
出现错误:****
请修改后,提供完整代码(不需我再更改,可以复制粘贴后直接使用)

【Deepseek输出V4.0代码】此时代码可以正常运行,接下来进行打包。

#我需要将该程序打包,使用exe文件,我该使用什么命令打包它?

【Deepseek给出打包命令,文件夹位置,对V4.0代码进行补充,V4.1】

V4.1完整版代码

import tkinter as tk

from tkinter import ttk, messagebox

from datetime import datetime, timedelta

import matplotlib.pyplot as plt

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

from PIL import Image, ImageTk, ImageDraw

import csv

import os

import mplcursors

  

class TimeTrackerApp:

    def __init__(self, root):

        self.root = root

        self.root.title("学习时间追踪器")

        self.current_selection = None

        self.recording = False

        self.start_time = None

        self.records = []

        self.selected_record = None

        self.timer_id = None

        self.current_duration = 0

  

        # 初始化数据文件

        self.data_file = "records.csv"

        if not os.path.exists(self.data_file):

            with open(self.data_file, "w", newline="", encoding="utf-8") as f:

                writer = csv.writer(f)

                writer.writerow(["Date", "Category", "Duration", "TimeRange", "Type"])

  

        # 加载图标

        self.original_images = {}

        self.icons = {}

        self.load_icons()

        self.create_main_interface()

        self.load_records()

  

    def load_icons(self):

        # 获取打包后的资源路径

        if getattr(sys, 'frozen', False):

            base_path = sys._MEIPASS

        else:

            base_path = os.path.dirname(os.path.abspath(__file__))

        icon_path = base_path  # 图标直接放在根目录

        try:

            self.original_images = {

                "主动学习": Image.open(os.path.join(icon_path, "active_learning.jpg")).resize((80, 80)),

                "被动学习": Image.open(os.path.join(icon_path, "passive_learning.jpg")).resize((80, 80)),

                "创作": Image.open(os.path.join(icon_path, "creative.jpg")).resize((80, 80))

            }

            # ...保持后续处理不变...

            for cat, img in self.original_images.items():

                self.icons[cat] = self.create_rounded_rectangle(img)

        except Exception as e:

            messagebox.showerror("错误", f"图标加载失败: {str(e)}")

            exit()

  

    def create_rounded_rectangle(self, pil_image, radius=20):

        mask = Image.new("L", pil_image.size, 0)

        draw = ImageDraw.Draw(mask)

        draw.rounded_rectangle([(0, 0), pil_image.size], radius, fill=255)

        result = pil_image.copy()

        result.putalpha(mask)

        return ImageTk.PhotoImage(result)

  

    def create_main_interface(self):

        # 项目选择按钮

        self.category_frame = tk.Frame(self.root)

        self.category_frame.pack(pady=10)

  

        self.categories = ["主动学习", "被动学习", "创作"]

        self.buttons = []

        for i, cat in enumerate(self.categories):

            btn = tk.Button(self.category_frame,

                          image=self.icons[cat],

                          compound=tk.CENTER,

                          relief="flat",

                          bg="#f0f0f0",

                          borderwidth=0,

                          highlightthickness=0,

                          command=lambda c=cat: self.select_category(c))

            btn.grid(row=0, column=i, padx=5)

            self.buttons.append(btn)

  

        # 时间显示区域

        self.time_frame = tk.Frame(self.root)

        self.time_frame.pack(pady=10)

        self.start_label = tk.Label(self.time_frame, text="开始时间:未开始")

        self.start_label.grid(row=0, column=0, padx=5)

        self.duration_label = tk.Label(self.time_frame, text="已记录:0 分钟")

        self.duration_label.grid(row=0, column=1, padx=5)

        self.end_label = tk.Label(self.time_frame, text="结束时间:未结束")

        self.end_label.grid(row=0, column=2, padx=5)

  

        # 控制按钮

        self.control_frame = tk.Frame(self.root)

        self.control_frame.pack(pady=10)

  

        self.start_btn = tk.Button(self.control_frame, text="开始记录", command=self.start_recording)

        self.start_btn.grid(row=0, column=0, padx=5)

        self.end_btn = tk.Button(self.control_frame, text="结束记录", state="disabled", command=self.end_recording)

        self.end_btn.grid(row=0, column=1, padx=5)

  

        # 功能按钮

        self.function_btn_frame = tk.Frame(self.root)

        self.function_btn_frame.pack(pady=10)

        self.manual_btn = tk.Button(self.function_btn_frame, text="手动调整", command=self.open_manual_adjust)

        self.manual_btn.grid(row=0, column=0, padx=5)

        self.notebook_btn = tk.Button(self.function_btn_frame, text="笔记本", command=self.open_notebook)

        self.notebook_btn.grid(row=0, column=1, padx=5)

        self.chart_btn = tk.Button(self.function_btn_frame, text="折线图", command=self.show_chart)

        self.chart_btn.grid(row=0, column=2, padx=5)

  

    def select_category(self, category):

        if self.current_selection:

            self.buttons[self.categories.index(self.current_selection)].config(bg="#f0f0f0")

        self.current_selection = category

        self.buttons[self.categories.index(category)].config(bg="#c0e0ff")

  

    def start_recording(self):

        if not self.current_selection:

            messagebox.showwarning("警告", "请先选择项目")

            return

        self.recording = True

        self.start_time = datetime.now()

        self.start_label.config(text=f"开始时间:{self.start_time.strftime('%H:%M')}")

        self.duration_label.config(text="已记录:0 分钟")

        self.end_label.config(text="结束时间:未结束")

        self.start_btn.config(state="disabled")

        self.end_btn.config(state="normal")

        self.current_duration = 0

        self.update_timer()

  

    def end_recording(self):

        if not self.recording:

            return

        self.recording = False

        end_time = datetime.now()

        duration = (end_time - self.start_time).seconds // 60

        self.save_record(

            self.start_time.strftime("%Y-%m-%d"),

            self.current_selection,

            duration,

            f"{self.start_time.strftime('%H:%M')}-{end_time.strftime('%H:%M')}",

            "自动"

        )

        self.end_label.config(text=f"结束时间:{end_time.strftime('%H:%M')}")

        self.start_btn.config(state="normal")

        self.end_btn.config(state="disabled")

        if self.timer_id:

            self.root.after_cancel(self.timer_id)

  

    def update_timer(self):

        if self.recording:

            self.current_duration += 1

            self.duration_label.config(text=f"已记录:{self.current_duration} 分钟")

            self.timer_id = self.root.after(60000, self.update_timer)

  

    def save_record(self, date, category, duration, time_range, record_type):

        if self.check_time_overlap(date, time_range):

            messagebox.showwarning("时间冲突", "检测到时间重叠,请检查后重新记录")

            return

  

        with open(self.data_file, "a", newline="", encoding="utf-8") as f:

            writer = csv.writer(f)

            writer.writerow([date, category, duration, time_range, record_type])

        self.load_records()

  

    def check_time_overlap(self, date, new_time_range):

        new_start, new_end = [datetime.strptime(t, "%H:%M") for t in new_time_range.split("-")]

        for record in self.records:

            if record["Date"] == date:

                existing_start, existing_end = [datetime.strptime(t, "%H:%M") for t in record["TimeRange"].split("-")]

                if (new_start < existing_end) and (new_end > existing_start):

                    return True

        return False

  

    def load_records(self):

        self.records = []

        with open(self.data_file, "r", encoding="utf-8") as f:

            reader = csv.DictReader(f)

            for row in reader:

                self.records.append(row)

  

    def open_manual_adjust(self):

        self.manual_window = tk.Toplevel(self.root)

        self.manual_window.title("手动调整")

        self.manual_category = tk.StringVar(value="")  # 默认不选择

        tk.Label(self.manual_window, text="选择项目:").grid(row=0, column=0, padx=5, pady=5)

        for i, cat in enumerate(self.categories):

            rb = tk.Radiobutton(self.manual_window,

                              image=self.icons[cat],

                              variable=self.manual_category,

                              value=cat)

            rb.grid(row=0, column=i+1, padx=5)

  

        tk.Label(self.manual_window, text="日期 (YYYY-MM-DD):").grid(row=1, column=0, padx=5, pady=5)

        self.date_entry = tk.Entry(self.manual_window)

        self.date_entry.grid(row=1, column=1, columnspan=3)

  

        tk.Label(self.manual_window, text="开始时间 (HH:MM):").grid(row=2, column=0, padx=5, pady=5)

        self.start_entry = tk.Entry(self.manual_window)

        self.start_entry.grid(row=2, column=1, columnspan=3)

  

        tk.Label(self.manual_window, text="结束时间 (HH:MM):").grid(row=3, column=0, padx=5, pady=5)

        self.end_entry = tk.Entry(self.manual_window)

        self.end_entry.grid(row=3, column=1, columnspan=3)

  

        save_btn = tk.Button(self.manual_window, text="保存记录", command=self.save_manual_record)

        save_btn.grid(row=4, column=1, pady=10)

  

    def save_manual_record(self):

        try:

            # 检查项目是否选择

            if not self.manual_category.get():

                messagebox.showwarning("警告", "当前未选择项目")

                return

  

            date_str = self.date_entry.get()

            start_str = self.start_entry.get()

            end_str = self.end_entry.get()

            date = datetime.strptime(date_str, "%Y-%m-%d").date()

            start_time = datetime.strptime(start_str, "%H:%M").time()

            end_time = datetime.strptime(end_str, "%H:%M").time()

            start_datetime = datetime.combine(date, start_time)

            end_datetime = datetime.combine(date, end_time)

            if end_datetime <= start_datetime:

                raise ValueError("结束时间必须晚于开始时间")

            duration = (end_datetime - start_datetime).seconds // 60

            self.save_record(

                date_str,

                self.manual_category.get(),

                duration,

                f"{start_str}-{end_str}",

                "手动"

            )

            messagebox.showinfo("成功", "记录已保存")

            self.manual_window.destroy()

        except Exception as e:

            messagebox.showerror("输入错误", f"无效输入: {str(e)}")

  

    def open_notebook(self):

        notebook_window = tk.Toplevel(self.root)

        notebook_window.title("学习记录")

        tree_frame = tk.Frame(notebook_window)

        tree_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

  

        btn_frame = tk.Frame(notebook_window)

        btn_frame.pack(pady=5)

  

        delete_btn = tk.Button(btn_frame, text="删除选中记录",

                             command=lambda: self.delete_selected_record(tree))

        delete_btn.pack(side=tk.LEFT, padx=5)

  

        tree = ttk.Treeview(tree_frame, columns=("Date", "Category", "Duration", "TimeRange"), show="headings")

        tree.heading("Date", text="日期")

        tree.heading("Category", text="类型")

        tree.heading("Duration", text="时长(分钟)")

        tree.heading("TimeRange", text="时间范围")

        vsb = ttk.Scrollbar(tree_frame, orient="vertical", command=tree.yview)

        tree.configure(yscrollcommand=vsb.set)

        tree.grid(row=0, column=0, sticky="nsew")

        vsb.grid(row=0, column=1, sticky="ns")

        tree_frame.grid_columnconfigure(0, weight=1)

        tree_frame.grid_rowconfigure(0, weight=1)

  

        for record in self.records:

            tree.insert("", "end", values=(

                record["Date"],

                record["Category"],

                record["Duration"],

                record["TimeRange"]

            ))

  

        tree.bind("<Button-3>", lambda e: self.show_context_menu(tree, e))

  

    def delete_selected_record(self, tree):

        selected = tree.selection()

        if not selected:

            messagebox.showwarning("警告", "请先选择要删除的记录")

            return

        if messagebox.askyesno("确认", "确定要删除选中的记录吗?"):

            for item in selected:

                values = tree.item(item, "values")

                self.remove_from_csv(values)

                tree.delete(item)

            self.load_records()

  

    def remove_from_csv(self, values):

        temp_file = self.data_file + ".tmp"

        with open(self.data_file, "r", encoding="utf-8") as fin, \

             open(temp_file, "w", newline="", encoding="utf-8") as fout:

            reader = csv.reader(fin)

            writer = csv.writer(fout)

            header = next(reader)

            writer.writerow(header)

            for row in reader:

                if (row[0], row[1], row[2], row[3]) != (values[0], values[1], values[2], values[3]):

                    writer.writerow(row)

        os.replace(temp_file, self.data_file)

  

    def show_chart(self):

        chart_window = tk.Toplevel(self.root)

        chart_window.title("学习时长统计")

        daily_data = {}

        for record in self.records:

            date = record["Date"]

            duration = int(record["Duration"])

            daily_data[date] = daily_data.get(date, 0) + duration

        sorted_dates = sorted(daily_data.items(), key=lambda x: datetime.strptime(x[0], "%Y-%m-%d"))

        fig = plt.figure(figsize=(8, 4))

        ax = fig.add_subplot(111)

        # 隐藏所有坐标轴元素

        ax.set_xticks([])

        ax.set_yticks([])

        ax.set_xticklabels([])

        ax.set_yticklabels([])

        ax.spines['top'].set_visible(False)

        ax.spines['right'].set_visible(False)

        ax.spines['bottom'].set_visible(False)

        ax.spines['left'].set_visible(False)

        line, = ax.plot(

            [x[0] for x in sorted_dates],

            [x[1] for x in sorted_dates],

            marker="o",

            linestyle="-",

            markersize=8,

            linewidth=2

        )

  

        # 设置悬停提示

        cursor = mplcursors.cursor(line, hover=True)

        @cursor.connect("add")

        def on_add(sel):

            date = sorted_dates[sel.index][0]

            duration = sorted_dates[sel.index][1]

            sel.annotation.set(text=f"{date}\n{duration}min",

                              bbox=dict(boxstyle="round,pad=0.5", facecolor="white", alpha=0.9))

            sel.annotation.arrow_patch.set(arrowstyle="->", color="black")

        canvas = FigureCanvasTkAgg(fig, master=chart_window)

        canvas.draw()

        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

  

    def show_context_menu(self, tree, event):

        item = tree.identify_row(event.y)

        if item:

            menu = tk.Menu(self.root, tearoff=0)

            menu.add_command(label="删除", command=lambda: self.delete_record(tree, item))

            menu.post(event.x_root, event.y_root)

  

    def delete_record(self, tree, item):

        if messagebox.askyesno("确认", "确定要删除这条记录吗?"):

            values = tree.item(item, "values")

            self.remove_from_csv(values)

            tree.delete(item)

  

if __name__ == "__main__":

    root = tk.Tk()

    app = TimeTrackerApp(root)

    root.mainloop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值