# 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()