目录
欢迎认识,我是扑克中的黑桃A
扑克中的黑桃A的256天创作纪念日
扑克中的黑桃A的个人主页
前言:与 CSDN 的第二次相遇
当鼠标点击 “发布” 按钮的那一刻,距离我在 CSDN 写下第一篇博客《Pycharm 的好用设置和插件》已经过去了 256 天。如果说 128 天是创作旅程的起点,那么此刻的我更像是站在技术成长的半山腰,回望来时的路,每一步都刻着代码的温度与社区的回响。这封报告不仅是对 256 天创作历程的复盘,更是一次与技术、与自我、与社区的深度对话。
沉淀:在基础领域凿出技术深井
量化成长:从 0 到 1 的扎实积累
内容矩阵:累计发布68篇原创,其中金仓数据库征文-政务领域国产化数据库更替:金仓 KingbaseES 应用实践这篇征文阅读量更是高达39580,这是以前没有想过的数据。
热榜排名:也有许多文章上了热榜,其中,AI对话高效输入指令攻略(一):了解AI对话指令更是在榜一霸榜三天
今天的数据和128天前的纪念日时相比,已经有一个层的变化了。
这 256天的创作,是一场充满惊喜的旅程。粉丝数量逐步增长,目前已有4546位朋友关注,他们的每一次关注,都让我深感责任重大。文章总阅读量已经到了253,108人次,排名从5333到了2150,让我备受鼓舞。
文章累计收获4779个赞、2904条评论和4014的收藏量。评论区里,既有新手的感谢,也有同行的建议。 甚至成了Python领域新星创作者,还入选了作者榜。
头衔增加:技术能力的突破
这128天,继续获得了阿里云专家博主,腾讯云TDP先锋会员,腾讯云创作之星,华为云初级校园大使等多个名号。
日常
创作已经在我大学生活中扮演着重要的角色。每当课余时间到来,我都会先回顾当天学到的知识,思考如何将所学运用到我的创作之中。有时灵感乍现,即便是在课间休息的短暂片刻,我也会迅速将思路记录在笔记本上。
晚上完成作业后,我会静坐在电脑前,投入一到两个小时的时间整理素材、编写代码、撰写文章。周末则是我专门留给创作的时间,更深入地学习新的 Python 库和框架,为我的创作积累更多内容和技巧。
虽然在创作与其他学业之间保持平衡并不容易,但我总是制定详细的学习计划,合理分配时间。例如,我会在周一到周五集中精力完成课程学习,而将周末的特定时段专门用于创作和深度学习,确保两者都得到充分的关注和发展。这样的安排让我能够保持学业与创作的双赢,让我在学习和创作之间找到了完美的平衡点。
成就
128天前写的是跳动的爱心(李洵同款),现在的是秒序任务待办清单。
import tkinter as tk
from tkinter import filedialog, colorchooser, messagebox
from PIL import Image, ImageTk
import json
from pathlib import Path
from datetime import datetime
from tkinter import ttk
class AdvancedTaskManager:
def __init__(self, root):
self.root = root
self.root.title("秒序任务待办清单")
self.tasks = []
self.data_file = Path("tasks.json")
self.drag_start_index = None
self.sort_mode = tk.StringVar(value="auto")
self.sort_criteria = tk.StringVar(value="priority") # 新增排序依据
self.custom_order = []
self.checkbox_width = 4
self.bg_image = None
self.bg_photo = None
# 初始化背景
self.background_label = tk.Label(self.root)
self.background_label.place(relx=0, rely=0, relwidth=1, relheight=1)
# 样式管理 Combobox 背景色
self.combo_style = ttk.Style()
self.combo_style.map('Custom.TCombobox',
fieldbackground=[('readonly', 'white')],
selectbackground=[('readonly', 'white')],
selectforeground=[('readonly', 'black')])
# 创建界面组件
self.create_widgets()
# 加载任务数据
self.load_tasks()
# 初始更新列表显示
self.update_lists()
# 设置窗口关闭事件
self.root.protocol("WM_DELETE_WINDOW", self.on_close)
def create_widgets(self):
# ================== 左侧任务列表区域 ==================
list_container = tk.Frame(self.root, bd=2, relief=tk.GROOVE)
list_container.pack(side=tk.LEFT, padx=10, pady=10, fill=tk.BOTH, expand=True)
# 分割线标签 - 未完成任务
tk.Label(list_container, text="未完成任务", font=("微软雅黑", 12, "bold")).pack(anchor='w', pady=(5, 0))
# 未完成任务列表
ongoing_frame = tk.Frame(list_container)
ongoing_frame.pack(fill=tk.BOTH, expand=True)
ongoing_scrollbar = tk.Scrollbar(ongoing_frame)
ongoing_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.ongoing_list = tk.Listbox(
ongoing_frame,
yscrollcommand=ongoing_scrollbar.set,
font=('微软雅黑', 11),
selectbackground="#1E90FF",
selectforeground="white",
selectmode=tk.SINGLE,
height=8,
width=50,
activestyle="none",
bg="white"
)
self.ongoing_list.pack(fill=tk.BOTH, expand=True)
ongoing_scrollbar.config(command=self.ongoing_list.yview)
# 分隔空间
tk.Frame(list_container, height=10).pack()
# 已完成任务标题
tk.Label(list_container, text="已完成任务", font=("微软雅黑", 12, "bold")).pack(anchor='w', pady=(5, 0))
# 已完成任务列表
completed_frame = tk.Frame(list_container)
completed_frame.pack(fill=tk.BOTH, expand=True)
completed_scrollbar = tk.Scrollbar(completed_frame)
completed_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.completed_list = tk.Listbox(
completed_frame,
yscrollcommand=completed_scrollbar.set,
font=('微软雅黑', 11),
selectbackground="#1E90FF",
selectforeground="white",
selectmode=tk.SINGLE,
height=7,
width=50,
activestyle="none",
bg="white"
)
self.completed_list.pack(fill=tk.BOTH, expand=True)
completed_scrollbar.config(command=self.completed_list.yview)
# 绑定事件
self.ongoing_list.bind('<Button-1>', self.on_click)
self.ongoing_list.bind('<Button-3>', self.show_context_menu)
self.completed_list.bind('<Button-1>', self.on_click)
self.completed_list.bind('<Button-3>', self.show_context_menu)
# ================== 右侧控制面板区域 ==================
control_frame = tk.Frame(self.root)
control_frame.pack(side=tk.RIGHT, padx=10, pady=10, fill=tk.Y)
# 输入表单
input_frame = tk.LabelFrame(control_frame, text="任务详情", padx=10, pady=10, bg="white")
input_frame.pack(pady=10)
tk.Label(input_frame, text="任务名称:", bg="white").grid(row=0, column=0, sticky='w')
self.task_entry = tk.Entry(input_frame, width=25, bg="white")
self.task_entry.grid(row=1, column=0, pady=5, sticky='we')
tk.Label(input_frame, text="优先级(1-5):", bg="white").grid(row=2, column=0, sticky='w')
# 使用自定义样式组合框
self.priority_combo = ttk.Combobox(
input_frame,
width=23,
values=[1, 2, 3, 4, 5],
style='Custom.TCombobox'
)
self.priority_combo.grid(row=3, column=0, pady=5)
tk.Label(input_frame, text="截止日期(yyyy.mm.dd):", bg="white").grid(row=4, column=0, sticky='w')
self.due_date_entry = tk.Entry(input_frame, width=25, bg="white")
self.due_date_entry.grid(row=5, column=0, pady=5)
# 操作按钮
btn_frame = tk.Frame(control_frame, bg=self.root.cget('bg'))
btn_frame.pack(pady=15)
self.add_btn = self.create_button(btn_frame, "添加任务", "#4CAF50", self.add_task)
self.add_btn.grid(row=0, column=0, padx=5)
self.del_btn = self.create_button(btn_frame, "删除任务", "#ff4444", self.delete_task)
self.del_btn.grid(row=0, column=1, padx=5)
# 移动控制
move_frame = tk.Frame(control_frame, bg=self.root.cget('bg'))
move_frame.pack(pady=10)
self.move_up_btn = self.create_button(move_frame, "↑ 上移", "#2196F3", self.move_up, width=10)
self.move_down_btn = self.create_button(move_frame, "↓ 下移", "#2196F3", self.move_down, width=10)
self.move_up_btn.pack(side=tk.LEFT, padx=5)
self.move_down_btn.pack(side=tk.RIGHT, padx=5)
# 排序模式选择
mode_frame = tk.Frame(control_frame)
mode_frame.pack(pady=5)
tk.Label(mode_frame, text="排序模式:", bg=self.root.cget('bg')).pack(side=tk.LEFT)
tk.Radiobutton(
mode_frame,
text="自动排序",
variable=self.sort_mode,
value="auto",
command=self.update_move_buttons_visibility
).pack(side=tk.LEFT)
tk.Radiobutton(
mode_frame,
text="手动排序",
variable=self.sort_mode,
value="manual",
command=self.update_move_buttons_visibility
).pack(side=tk.LEFT)
# 排序依据选择(仅自动排序时可用)
criteria_frame = tk.Frame(control_frame)
criteria_frame.pack(pady=5)
self.criteria_priority_rb = tk.Radiobutton(
criteria_frame,
text="按优先级",
variable=self.sort_criteria,
value="priority",
command=self.sort_tasks
)
self.criteria_due_date_rb = tk.Radiobutton(
criteria_frame,
text="按截止日期",
variable=self.sort_criteria,
value="due_date",
command=self.sort_tasks
)
self.criteria_priority_rb.pack(side=tk.LEFT)
self.criteria_due_date_rb.pack(side=tk.LEFT)
# 设置背景按钮
bg_frame = tk.Frame(control_frame, bg=self.root.cget('bg'))
bg_frame.pack(pady=10)
self.create_button(bg_frame, "设置模块颜色", "#808080", self.set_background_color, width=20).pack(pady=2)
self.create_button(bg_frame, "上传背景图片", "#808080", self.upload_background_image, width=20).pack(pady=2)
self.create_button(bg_frame, "恢复默认背景", "#808080", self.reset_background, width=20).pack(pady=2)
# 初始化控件状态
self.update_move_buttons_visibility()
def create_button(self, parent, text, color, command, width=12):
return tk.Button(
parent,
text=text,
command=command,
bg=color,
fg="white",
width=width,
relief="flat",
activebackground=color,
highlightthickness=0
)
def update_move_buttons_visibility(self):
if self.sort_mode.get() == "manual":
self.move_up_btn.pack(side=tk.LEFT, padx=5)
self.move_down_btn.pack(side=tk.RIGHT, padx=5)
self.criteria_priority_rb.config(state=tk.DISABLED)
self.criteria_due_date_rb.config(state=tk.DISABLED)
else:
self.move_up_btn.pack_forget()
self.move_down_btn.pack_forget()
self.criteria_priority_rb.config(state=tk.NORMAL)
self.criteria_due_date_rb.config(state=tk.NORMAL)
self.sort_tasks()
def set_background_color(self):
color = colorchooser.askcolor()[1]
if color:
if hasattr(self, 'bg_image'):
del self.bg_image
self.background_label.configure(image='')
self.root.configure(bg=color)
for widget in self.root.winfo_children():
widget_type = widget.winfo_class()
if widget_type not in ('Listbox', 'Entry', 'TCombobox', 'LabelFrame'):
widget.configure(bg=color)
if isinstance(widget, tk.Scrollbar):
widget.configure(troughcolor=color)
self.task_entry.configure(bg="white")
self.due_date_entry.configure(bg="white")
self.ongoing_list.configure(bg="white")
self.completed_list.configure(bg="white")
# 修改 Combobox 样式
self.combo_style.configure('Custom.TCombobox', fieldbackground="white", background="white")
def upload_background_image(self):
file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png *.jpg *.jpeg *.gif *.bmp")])
if file_path:
try:
# 打开图像并删除可能存在的错误 ICC Profile
image = Image.open(file_path)
if "icc_profile" in image.info:
icc_data = image.info.get("icc_profile", b'')
if icc_data:
# 创建一个不带 ICC 的新图像副本
image_data = list(image.getdata())
image = Image.new(image.mode, image.size)
image.putdata(image_data)
self.bg_image = image.convert("RGBA")
self.update_background_image()
self.root.bind("<Configure>", self.resize_background)
except Exception as e:
messagebox.showerror("错误", f"无法加载背景图: {str(e)}")
def resize_background(self, event=None):
if hasattr(self, 'bg_image'):
resized = self.bg_image.resize((self.root.winfo_width(), self.root.winfo_height()), Image.Resampling.LANCZOS)
self.bg_photo = ImageTk.PhotoImage(resized)
self.background_label.configure(image=self.bg_photo)
self.background_label.lower()
def update_background_image(self):
self.resize_background()
def reset_background(self):
default_color = "#f0f0f0"
self.root.configure(bg=default_color)
for widget in self.root.winfo_children():
widget_type = widget.winfo_class()
if widget_type not in ('Listbox', 'Entry', 'TCombobox', 'LabelFrame'):
widget.configure(bg=default_color)
if isinstance(widget, tk.Scrollbar):
widget.configure(troughcolor=default_color)
self.task_entry.configure(bg="white")
self.due_date_entry.configure(bg="white")
self.ongoing_list.configure(bg="white")
self.completed_list.configure(bg="white")
self.combo_style.configure('Custom.TCombobox', fieldbackground="white", background="white")
if hasattr(self, 'bg_image'):
del self.bg_image
self.background_label.configure(image='')
def on_click(self, event):
ongoing_selected = self.ongoing_list.nearest(event.y)
completed_selected = self.completed_list.nearest(event.y)
if ongoing_selected >= 0:
task_idx = ongoing_selected
if event.x < self.checkbox_width * 8:
self.toggle_task_status(task_idx, is_ongoing=True)
else:
self.select_task(task_idx, is_ongoing=True)
elif completed_selected >= 0:
task_idx = completed_selected
if event.x < self.checkbox_width * 8:
self.toggle_task_status(task_idx, is_ongoing=False)
else:
self.select_task(task_idx, is_ongoing=False)
def toggle_task_status(self, index, is_ongoing=True):
if is_ongoing:
task_idx = index
else:
offset = len([t for t in self.tasks if not t["completed"]])
task_idx = offset + index
if 0 <= task_idx < len(self.tasks):
current_state = self.tasks[task_idx]["completed"]
self.tasks[task_idx]["completed"] = not current_state
if self.tasks[task_idx]["completed"]:
self.tasks[task_idx]["completion_date"] = datetime.now().strftime("%Y.%m.%d %H:%M")
else:
self.tasks[task_idx].pop("completion_date", None)
self.update_lists()
self.save_tasks()
def select_task(self, index, is_ongoing=True):
self.clear_selections()
if is_ongoing:
self.ongoing_list.select_set(index)
else:
self.completed_list.select_set(index)
def clear_selections(self):
self.ongoing_list.select_clear(0, tk.END)
self.completed_list.select_clear(0, tk.END)
def update_lists(self):
self.ongoing_list.delete(0, tk.END)
self.completed_list.delete(0, tk.END)
for idx, task in enumerate(self.tasks):
status = "[✓]" if task["completed"] else "[ ]"
name = task["name"]
due_date = f" 📅 {task['due_date']}" if task['due_date'] else ""
priority = f"🔢 优先级:{task['priority']}"
create_date = f"🕒 创建于:{task['create_date']}"
if task["completed"]:
completion_info = f"✅ 完成于:{task.get('completion_date', '')}"
lines = [
f"{status} {name}",
f" {priority}{due_date}",
f" {create_date}",
f" {completion_info}"
]
self.completed_list.insert(tk.END, "\n".join(lines))
self.completed_list.itemconfig(tk.END, fg="#666666")
else:
lines = [
f"{status} {name}",
f" {priority}{due_date}",
f" {create_date}"
]
self.ongoing_list.insert(tk.END, "\n".join(lines))
self.ongoing_list.itemconfig(tk.END, fg="#000000")
def get_selected_index(self):
ongoing_sel = self.ongoing_list.curselection()
completed_sel = self.completed_list.curselection()
if ongoing_sel:
return ongoing_sel[0], True
elif completed_sel:
return completed_sel[0], False
else:
messagebox.showwarning("操作错误", "请先选择任务!")
return None, None
def delete_task(self):
index, is_ongoing = self.get_selected_index()
if index is None:
return
if is_ongoing:
task_idx = index
else:
offset = len([t for t in self.tasks if not t["completed"]])
task_idx = offset + index
del self.tasks[task_idx]
self.update_lists()
self.save_tasks()
def move_up(self):
index, is_ongoing = self.get_selected_index()
if index is None:
return
if is_ongoing and index > 0:
task_idx = index
prev_idx = index - 1
elif not is_ongoing and index > 0:
offset = len([t for t in self.tasks if not t["completed"]])
task_idx = offset + index
prev_idx = task_idx - 1
else:
return
self.tasks[task_idx], self.tasks[prev_idx] = self.tasks[prev_idx], self.tasks[task_idx]
self.sort_mode.set("custom")
self.update_lists()
self.save_tasks()
def move_down(self):
index, is_ongoing = self.get_selected_index()
if index is None:
return
if is_ongoing and index < self.ongoing_list.size() - 1:
task_idx = index
next_idx = index + 1
elif not is_ongoing and index < self.completed_list.size() - 1:
offset = len([t for t in self.tasks if not t["completed"]])
task_idx = offset + index
next_idx = task_idx + 1
else:
return
self.tasks[task_idx], self.tasks[next_idx] = self.tasks[next_idx], self.tasks[task_idx]
self.sort_mode.set("custom")
self.update_lists()
self.save_tasks()
def add_task(self):
task_name = self.task_entry.get().strip()
priority = self.priority_combo.get().strip()
due_date = self.due_date_entry.get().strip()
create_date = datetime.now().strftime("%Y.%m.%d %H:%M")
if not self.validate_input(task_name, priority, due_date):
return
new_task = {
"name": task_name,
"priority": int(priority),
"create_date": create_date,
"due_date": self.format_due_date(due_date),
"completed": False
}
if self.sort_mode.get() == "manual":
self.tasks.insert(0, new_task)
self.custom_order.insert(0, 0)
else:
self.insert_sorted(new_task)
self.update_lists()
self.save_tasks()
self.clear_inputs()
def validate_input(self, name, priority, due_date):
if not name:
messagebox.showwarning("错误", "请输入任务名称!")
return False
try:
if not 1 <= int(priority) <= 5:
raise ValueError
except ValueError:
messagebox.showwarning("错误", "优先级必须是1-5的整数!")
return False
if due_date and not self.is_valid_date(due_date):
messagebox.showwarning("错误", "日期格式无效,请使用 yyyy.mm.dd 格式!")
return False
return True
def is_valid_date(self, date_str):
try:
datetime.strptime(date_str, "%Y.%m.%d")
return True
except ValueError:
return False
def format_due_date(self, date_str):
if not date_str:
return ""
try:
return datetime.strptime(date_str, "%Y.%m.%d").strftime("%Y.%m.%d")
except:
return ""
def insert_sorted(self, new_task):
criteria = self.sort_criteria.get()
insert_pos = 0
for idx, task in enumerate(self.tasks):
if task["completed"]:
break
if criteria == "priority":
if new_task["priority"] > task["priority"]:
break
elif new_task["priority"] == task["priority"]:
if (new_task["due_date"] or "9999.99.99") < (task["due_date"] or "9999.99.99"):
break
elif criteria == "due_date":
if (new_task["due_date"] or "9999.99.99") < (task["due_date"] or "9999.99.99"):
break
elif new_task["due_date"] == task["due_date"]:
if new_task["priority"] > task["priority"]:
break
insert_pos += 1
self.tasks.insert(insert_pos, new_task)
def sort_tasks(self):
if self.sort_mode.get() != "auto":
return
ongoing_tasks = [t for t in self.tasks if not t["completed"]]
completed_tasks = [t for t in self.tasks if t["completed"]]
criteria = self.sort_criteria.get()
if criteria == "priority":
ongoing_tasks.sort(key=lambda x: (-x['priority'], x['due_date'] or "9999.99.99"))
elif criteria == "due_date":
ongoing_tasks.sort(key=lambda x: (x['due_date'] or "9999.99.99", -x['priority']))
self.tasks = ongoing_tasks + completed_tasks
self.sync_custom_order()
self.update_lists()
def sync_custom_order(self):
self.custom_order = list(range(len(self.tasks)))
def clear_inputs(self):
self.task_entry.delete(0, tk.END)
self.priority_combo.set('')
self.due_date_entry.delete(0, tk.END)
def save_tasks(self):
try:
data = {
'tasks': self.tasks,
'sort_mode': self.sort_mode.get(),
'sort_criteria': self.sort_criteria.get(),
'custom_order': self.custom_order
}
with open(self.data_file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
messagebox.showwarning("保存错误", f"数据保存失败: {str(e)}")
def load_tasks(self):
try:
if self.data_file.exists():
with open(self.data_file, 'r', encoding='utf-8') as f:
data = json.load(f)
self.tasks = data.get('tasks', [])
self.sort_mode.set(data.get('sort_mode', 'auto'))
self.sort_criteria.set(data.get('sort_criteria', 'priority'))
if self.sort_mode.get() == "manual" and 'custom_order' in data:
self.custom_order = data.get('custom_order')
else:
self.sort_tasks()
except Exception as e:
messagebox.showwarning("加载错误", f"数据加载失败: {str(e)}")
self.tasks = []
self.custom_order = []
def show_context_menu(self, event):
menu = tk.Menu(self.root, tearoff=0)
menu.add_command(label="删除任务", command=self.delete_task)
menu.add_command(label="置顶", command=lambda: self.move_to_top(event))
ongoing_selected = self.ongoing_list.nearest(event.y)
completed_selected = self.completed_list.nearest(event.y)
if completed_selected >= 0:
task_idx = len([t for t in self.tasks if not t["completed"]]) + completed_selected
if self.tasks[task_idx]["completed"]:
menu.add_command(label="撤销完成", command=lambda: self.undo_complete_task(task_idx))
try:
menu.tk_popup(event.x_root, event.y_root)
finally:
menu.grab_release()
def move_to_top(self, event):
pass
def undo_complete_task(self, task_idx):
if 0 <= task_idx < len(self.tasks):
self.tasks[task_idx]["completed"] = False
self.tasks[task_idx].pop("completion_date", None)
self.update_lists()
self.save_tasks()
def on_close(self):
self.save_tasks()
self.root.destroy()
if __name__ == "__main__":
root = tk.Tk()
root.geometry("1000x700")
root.configure(bg="#f0f0f0")
root.resizable(True, True)
app = AdvancedTaskManager(root)
root.mainloop()
演示如下
秒序任务待办清单
憧憬
在过去的 256 天里,我深刻领悟到成为一个真正的 "技术高手" 并不是靠追求复杂性和华丽的技巧,而是将基础概念理解得非常透彻,并且能够将其应用于实际场景中。从最简单的 range(1, 10, 2)
中延伸出 "步长在数据采样中的应用",让我感到比运行复杂神经网络更有成就感。这种能够将抽象编程概念转化为通俗易懂生活场景的能力,正是我未来想要继续专注的方向。
我愿意将自己定位为基础技术的 "解读者",致力于将那些看似晦涩难懂的概念转化为人人皆可理解的形式,让更多初学者在编程的学习起点就能看到技术之树的延伸方向。我相信,只有打好扎实的基础,才能在技术的道路上走得更远。
最后,我要衷心感谢每一位在评论区留下足迹的读者。正是因为有了你们的反馈和支持,这些关于基础技术的内容才变得生动有趣。我希望我们在代码的世界里,每一个 print
、每一个循环都能成为通往技术深处的路标,引领更多人走进编程的奇妙世界。未来的每一天,让我们一起努力,共同成长,共同探索,让技术之树在我们手中茁壮成长!