Python,速成心法
敲代码,查资料,问度娘
练习,探索,总结,优化
★★★★★博文创作不易,我的博文不需要打赏,也不需要知识付费,可以白嫖学习编程小技巧。使用代码的过程中,如有疑问的地方,欢迎大家指正留言交流。喜欢的老铁可以多多点赞+收藏分享+置顶,小红牛在此表示感谢。★★★★★
------------★Python练手项目源码★------------
Python项目27:用Tkinter写日志管理系统(中下等难度)
Python项目25:带滚动效果的商场抽奖系统(安排!!!)
Python项目24:基于Tkinter图形化界面,实现的学生课堂点名系统
Python项目22:一个简单的记账系统(收入+支出+查询)
Python项目源码20:银行管理系统(开户、查询、取款、存款、转账、锁定、解锁、退出)
Python项目18:使用Pillow模块,随机生成4位数的图片验证码
Python项目16:教你使用pillow把女神的图片,添加表白文字。
Python项目14:使用random,模拟扑克牌发牌+猜单词游戏
Python项目09:使用filestools模块,批量添加图片水印
Python项目08:用pywin32在聊天窗口发送QQ好友/群消息
Python小项目07:pywin32实现自动写文字到记事本
Python小项目05:使用pywifi模块,暴力破解WIFI密码 !!亲测有效
1.主要功能说明:在日志管理系统1.0功能基础上,继续升级优化2.0,如想要增加分类标签,标签下面放不同的日志标题。分类标签意味着日志可以按照不同的类别进行组织,比如工作、个人、项目等。每个标签下有自己的日志列表,用户可以通过切换标签来查看不同类别的日志。
4.json数据结构优化:
{
"categories": {
"工作日志": [
{"title": "项目进度", "content": "..."},
{"title": "会议记录", "content": "..."}
],
"个人笔记": [
{"title": "Python笔记", "content": "..."}
]
},
"current_category": "工作日志"
}
↓ 完整源码如下 ↓
# -*- coding: utf-8 -*-
# : 小红牛
# 微信公众号:WdPython
import tkinter as tk
from tkinter import ttk, messagebox, font, simpledialog
import json
import os
class CategorizedLogManager:
def __init__(self, root):
self.root = root
self.root.title("日志管理系统2.0————小红牛Python教程微信公众号:WdPython")
self.categories = {"默认分类": []}
self.current_category = "默认分类"
self.current_index = None
self.font_size = 12
self.default_font = ("楷体", 12)
self.search_keyword = ""
self.create_widgets()
self.load_data()
self.apply_font_settings()
def create_widgets(self):
# 主容器布局
main_frame = tk.Frame(self.root)
main_frame.pack(fill=tk.BOTH, expand=True)
# 左侧分类管理区域
left_panel = tk.Frame(main_frame, width=200)
left_panel.pack(side=tk.LEFT, fill=tk.Y)
# 分类操作按钮
category_btn_frame = tk.Frame(left_panel)
category_btn_frame.pack(fill=tk.X, pady=5)
ttk.Button(category_btn_frame, text="新建分类", command=self.new_category).pack(side=tk.LEFT, fill=tk.X,
expand=True)
ttk.Button(category_btn_frame, text="删除分类", command=self.delete_category).pack(side=tk.LEFT, fill=tk.X,
expand=True)
# 分类树状列表
self.category_tree = ttk.Treeview(left_panel, show="tree", selectmode="browse")
self.category_tree.pack(fill=tk.BOTH, expand=True, padx=5)
self.category_tree.bind("<<TreeviewSelect>>", self.on_category_selected)
# 右侧主内容区域
right_panel = tk.Frame(main_frame)
right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
# 工具栏
toolbar = tk.Frame(right_panel)
toolbar.pack(fill=tk.X, pady=5)
# 搜索框
search_frame = tk.Frame(toolbar)
search_frame.pack(side=tk.LEFT, padx=5)
ttk.Label(search_frame, text="搜索:").pack(side=tk.LEFT)
self.search_entry = ttk.Entry(search_frame, width=20)
self.search_entry.pack(side=tk.LEFT, padx=5)
self.search_entry.bind("<KeyRelease>", self.search_logs)
# 字体设置
font_frame = tk.Frame(toolbar)
font_frame.pack(side=tk.RIGHT, padx=5)
ttk.Label(font_frame, text="字号:").pack(side=tk.LEFT)
self.font_combobox = ttk.Combobox(font_frame,
values=[10, 12, 14, 16, 18, 20],
width=4)
self.font_combobox.pack(side=tk.LEFT)
self.font_combobox.set(12)
self.font_combobox.bind("<<ComboboxSelected>>", self.change_font_size)
# 日志操作按钮
log_btn_frame = tk.Frame(toolbar)
log_btn_frame.pack(side=tk.LEFT, padx=10)
ttk.Button(log_btn_frame, text="新建日志", command=self.new_log).pack(side=tk.LEFT)
ttk.Button(log_btn_frame, text="删除日志", command=self.delete_log).pack(side=tk.LEFT)
ttk.Button(log_btn_frame, text="移动日志", command=self.move_log).pack(side=tk.LEFT)
ttk.Button(log_btn_frame, text="置顶日志", command=self.move_to_top).pack(side=tk.LEFT)
tk.Button(log_btn_frame, text="上移日志", command=self.move_up).pack(side=tk.LEFT)
tk.Button(log_btn_frame, text="下移日志", command=self.move_down).pack(side=tk.LEFT)
ttk.Button(log_btn_frame, text="保存日志", command=self.save_log).pack(side=tk.LEFT)
# 日志列表
self.log_listbox = tk.Listbox(right_panel)
self.log_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
self.log_listbox.bind('<<ListboxSelect>>', self.on_log_selected)
# 日志编辑区域
editor_frame = tk.Frame(right_panel)
editor_frame.pack(fill=tk.BOTH, expand=True)
ttk.Label(editor_frame, text="标题").pack(anchor=tk.W)
self.title_entry = ttk.Entry(editor_frame)
self.title_entry.pack(fill=tk.X, pady=2)
ttk.Label(editor_frame, text="内容").pack(anchor=tk.W)
self.content_text = tk.Text(editor_frame, wrap=tk.WORD)
self.content_text.pack(fill=tk.BOTH, expand=True)
# 分类管理功能
def update_category_tree(self):
self.category_tree.delete(*self.category_tree.get_children())
for category in self.categories.keys():
self.category_tree.insert("", "end", text=category, values=(category,))
# 自动选择当前分类
children = self.category_tree.get_children()
if children:
for child in children:
if self.category_tree.item(child, "text") == self.current_category:
self.category_tree.selection_set(child)
break
def new_category(self):
name = simpledialog.askstring("新建分类", "请输入分类名称:")
if name:
if name in self.categories:
messagebox.showwarning("提示", "分类已存在!")
return
self.categories[name] = []
self.current_category = name
self.update_category_tree()
self.save_data()
def delete_category(self):
selected = self.category_tree.selection()
if selected:
category = self.category_tree.item(selected[0], "text")
if category == "默认分类":
messagebox.showwarning("提示", "默认分类不能删除")
return
if messagebox.askyesno("确认", f"确定要删除分类【{category}】及其所有日志吗?"):
# 转移日志到默认分类
self.categories["默认分类"].extend(self.categories[category])
del self.categories[category]
self.current_category = "默认分类"
self.update_category_tree()
self.refresh_log_list()
self.save_data()
def on_category_selected(self, event):
selected = self.category_tree.selection()
if selected:
new_category = self.category_tree.item(selected[0], "text")
if new_category != self.current_category:
self.current_category = new_category
self.refresh_log_list()
# 日志管理功能
def refresh_log_list(self):
self.log_listbox.delete(0, tk.END)
logs = self.get_current_logs()
for log in logs:
if self.search_keyword.lower() in log['title'].lower():
self.log_listbox.insert(tk.END, log['title'])
if self.current_index is not None and self.current_index < self.log_listbox.size():
self.log_listbox.selection_set(self.current_index)
def get_current_logs(self):
return self.categories[self.current_category]
def new_log(self):
logs = self.get_current_logs()
logs.append({'title': '新建日志', 'content': ''})
self.current_index = len(logs) - 1
self.refresh_log_list()
self.log_listbox.selection_clear(0, tk.END)
self.log_listbox.selection_set(tk.END)
self.on_log_selected(None)
self.save_data()
def delete_log(self):
if self.current_index is not None:
logs = self.get_current_logs()
if messagebox.askyesno("确认", "确定要删除这个日志吗?"):
del logs[self.current_index]
self.current_index = None
self.refresh_log_list()
self.title_entry.delete(0, tk.END)
self.content_text.delete('1.0', tk.END)
self.save_data()
def save_log(self):
if self.current_index is not None:
logs = self.get_current_logs()
title = self.title_entry.get()
content = self.content_text.get('1.0', tk.END).strip()
logs[self.current_index]['title'] = title
logs[self.current_index]['content'] = content
self.refresh_log_list()
self.save_data()
messagebox.showinfo("提示", "保存成功")
def on_log_selected(self, event):
selection = self.log_listbox.curselection()
if selection:
self.current_index = selection[0]
logs = self.get_current_logs()
filtered_logs = [log for log in logs
if self.search_keyword.lower() in log['title'].lower()]
actual_index = logs.index(filtered_logs[self.current_index])
self.title_entry.delete(0, tk.END)
self.title_entry.insert(0, logs[actual_index]['title'])
self.content_text.delete('1.0', tk.END)
self.content_text.insert('1.0', logs[actual_index]['content'])
self.current_index = actual_index
# 日志位置调整
def move_to_top(self):
logs = self.get_current_logs()
if self._validate_selection(logs):
selected_log = logs.pop(self.current_index)
logs.insert(0, selected_log)
self.current_index = 0
self.refresh_log_list()
self.save_data()
def move_up(self):
logs = self.get_current_logs()
if self._validate_selection(logs) and self.current_index > 0:
# 上移一位
logs[self.current_index], logs[self.current_index - 1] = \
logs[self.current_index - 1], logs[self.current_index]
self.current_index -= 1
self.refresh_log_list()
self.save_data()
def move_down(self):
logs = self.get_current_logs()
if self._validate_selection(logs) and self.current_index < len(logs) - 1:
# 下移一位
logs[self.current_index], logs[self.current_index + 1] = \
logs[self.current_index + 1], logs[self.current_index]
self.current_index += 1
self.refresh_log_list()
self.save_data()
def move_log(self):
logs = self.get_current_logs()
if self.current_index is None or not logs:
return
categories = list(self.categories.keys())
target = simpledialog.askstring(
"移动日志",
"请输入目标分类名称:",
initialvalue=self.current_category
)
if target and target in categories and target != self.current_category:
log = logs.pop(self.current_index)
self.categories[target].append(log)
self.current_index = None
self.refresh_log_list()
self.save_data()
def _validate_selection(self, logs):
if self.current_index is None or not logs:
messagebox.showwarning("提示", "请先选择要操作的日志")
return False
return True
# 搜索功能
def search_logs(self, event=None):
self.search_keyword = self.search_entry.get().strip()
self.refresh_log_list()
# 字体设置
def apply_font_settings(self):
new_font = font.Font(family=self.default_font[0], size=self.font_size)
self.title_entry.config(font=new_font)
self.content_text.config(font=new_font)
def change_font_size(self, event=None):
try:
self.font_size = int(self.font_combobox.get())
self.apply_font_settings()
except ValueError:
pass
# 数据持久化
def save_data(self):
data = {
"categories": self.categories,
"current_category": self.current_category,
"font_size": self.font_size
}
with open('categorized_logs.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
def load_data(self):
if os.path.exists('categorized_logs.json'):
try:
with open('categorized_logs.json', 'r', encoding='utf-8') as f:
data = json.load(f)
self.categories = data.get("categories", {"默认分类": []})
self.current_category = data.get("current_category", "默认分类")
self.font_size = data.get("font_size", 12)
self.font_combobox.set(self.font_size)
except Exception as e:
messagebox.showerror("错误", f"加载数据失败: {str(e)}")
self.update_category_tree()
self.refresh_log_list()
if __name__ == "__main__":
root = tk.Tk()
app = CategorizedLogManager(root)
root.mainloop()
完毕!!感谢您的收看
----------★★历史博文集合★★----------
Xpath 正则表达式 Selenium Etree Css
数据可视化 matplotlib 词云图 Pyecharts