Python基于wxPython實現(xiàn)TodoList任務管理器開發(fā)詳解
前言
在日常工作和學習中,任務管理是提高效率的重要工具。本文將詳細介紹如何使用Python的wxPython GUI框架開發(fā)一個功能完善的TodoList任務管理器。這個項目不僅適合wxPython初學者學習GUI編程,也能作為實用工具直接使用。
項目概述
核心功能
- 任務的增刪改查(CRUD)操作
- 任務優(yōu)先級管理(高/中/低)
- 任務分類管理
- 截止日期設置
- 多條件篩選和搜索
- 任務完成狀態(tài)切換
- 數據持久化存儲
- 實時統(tǒng)計信息顯示
- 鍵盤快捷操作
技術棧
- Python 3.x
- wxPython:跨平臺GUI框架
- JSON:數據存儲格式
運行結果

代碼結構分析
1. 模塊導入
import wx import wx.adv import wx.lib.mixins.listctrl as listmix import json import os from datetime import datetime, date
關鍵模塊說明:
wx:wxPython核心模塊wx.adv:高級控件模塊,提供DatePickerCtrl等控件wx.lib.mixins.listctrl:ListCtrl的混入類,提供自動列寬調整功能json:用于數據的序列化和持久化datetime:處理日期時間
2. TodoListCtrl類 - 自定義列表控件
class TodoListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, style=wx.LC_REPORT | wx.LC_SINGLE_SEL)
listmix.ListCtrlAutoWidthMixin.__init__(self)
設計要點:
1.多重繼承:同時繼承wx.ListCtrl和ListCtrlAutoWidthMixin
wx.ListCtrl:提供列表顯示功能ListCtrlAutoWidthMixin:自動調整最后一列寬度,優(yōu)化顯示效果
2.樣式設置:
wx.LC_REPORT:報表視圖模式,支持多列顯示wx.LC_SINGLE_SEL:單選模式,一次只能選擇一個項目
3.列定義:
self.InsertColumn(0, "完成", width=50) # 完成狀態(tài)標記 self.InsertColumn(1, "任務", width=250) # 任務名稱 self.InsertColumn(2, "優(yōu)先級", width=70) # 優(yōu)先級 self.InsertColumn(3, "分類", width=100) # 任務分類 self.InsertColumn(4, "截止日期", width=100) # 截止日期 self.InsertColumn(5, "創(chuàng)建日期", width=100) # 創(chuàng)建時間
3. TaskDialog類 - 任務編輯對話框
這是整個程序中最復雜的類,負責任務的添加和編輯。
3.1 初始化方法
def __init__(self, parent, title="添加任務", task_data=None):
super().__init__(None, title=title, size=(450, 400))
self.task_data = task_data
self.init_ui()
if task_data:
self.load_task_data(task_data)
# 綁定鍵盤事件
self.Bind(wx.EVT_CHAR_HOOK, self.on_key_press)
關鍵點:
parent參數設為None:使對話框獨立顯示,不受主窗口約束task_data:如果提供則為編輯模式,否則為添加模式EVT_CHAR_HOOK:全局鍵盤事件,實現(xiàn)回車鍵導航功能
3.2 鍵盤導航實現(xiàn)
def on_key_press(self, event):
keycode = event.GetKeyCode()
# 回車鍵模擬Tab鍵(切換焦點)
if keycode == wx.WXK_RETURN or keycode == wx.WXK_NUMPAD_ENTER:
focused = self.FindFocus()
# 如果焦點在確定按鈕上,則提交對話框
if isinstance(focused, wx.Button) and focused.GetId() == wx.ID_OK:
self.EndModal(wx.ID_OK)
return
# 如果焦點在多行文本框,允許換行
if isinstance(focused, wx.TextCtrl) and focused.HasFlag(wx.TE_MULTILINE):
event.Skip()
return
# 否則模擬Tab鍵,切換到下一個控件
focused.Navigate()
else:
event.Skip()
實現(xiàn)原理:
捕獲回車鍵事件
判斷當前焦點控件類型
根據不同控件采取不同行為:
- 確定按鈕:提交對話框
- 多行文本框:允許換行
- 其他控件:切換到下一個控件
3.3 UI布局
對話框使用垂直BoxSizer布局,包含以下控件:
任務名稱輸入框:
self.task_input = wx.TextCtrl(panel, size=(300, -1))
任務描述(多行文本):
self.desc_input = wx.TextCtrl(panel, size=(300, 80),
style=wx.TE_MULTILINE)
優(yōu)先級選擇:
self.priority_choice = wx.Choice(panel, choices=["高", "中", "低"]) self.priority_choice.SetSelection(1) # 默認選擇"中"
日期選擇器:
self.date_picker = wx.adv.DatePickerCtrl(panel,
style=wx.adv.DP_DROPDOWN | wx.adv.DP_SHOWCENTURY)
self.no_date_cb = wx.CheckBox(panel, label="無截止日期")
設計亮點:
- 提供"無截止日期"復選框,滿足不同需求
- 日期選擇器使用下拉樣式,操作便捷
3.4 數據加載和獲取
加載任務數據(編輯模式):
def load_task_data(self, data):
self.task_input.SetValue(data.get('name', ''))
self.desc_input.SetValue(data.get('description', ''))
priority_map = {"高": 0, "中": 1, "低": 2}
self.priority_choice.SetSelection(priority_map.get(data.get('priority', '中'), 1))
self.category_input.SetValue(data.get('category', ''))
if data.get('due_date'):
try:
due_date = datetime.strptime(data['due_date'], "%Y-%m-%d").date()
wx_date = wx.DateTime()
wx_date.Set(due_date.day, due_date.month - 1, due_date.year)
self.date_picker.SetValue(wx_date)
except:
pass
self.no_date_cb.SetValue(not data.get('due_date'))
注意事項:
- wxPython的月份從0開始,需要減1
- 使用try-except處理日期解析異常
獲取任務數據:
def get_task_data(self):
due_date = None
if not self.no_date_cb.GetValue():
wx_date = self.date_picker.GetValue()
due_date = f"{wx_date.GetYear()}-{wx_date.GetMonth()+1:02d}-{wx_date.GetDay():02d}"
return {
'name': self.task_input.GetValue(),
'description': self.desc_input.GetValue(),
'priority': self.priority_choice.GetStringSelection(),
'category': self.category_input.GetValue(),
'due_date': due_date,
'completed': self.task_data.get('completed', False) if self.task_data else False,
'created_date': self.task_data.get('created_date') if self.task_data else datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
數據結構設計:
- 使用字典存儲任務信息
- 日期格式統(tǒng)一為
YYYY-MM-DD - 創(chuàng)建時間精確到秒
4. TodoListFrame類 - 主窗口
這是程序的核心類,管理整個應用的UI和邏輯。
4.1 初始化
def __init__(self):
super().__init__(None, title="Todo List 任務管理器", size=(900, 650))
self.tasks = []
self.data_file = "todolist_data.json"
self.load_data()
self.init_ui()
self.Centre()
self.Show()
初始化流程:
- 創(chuàng)建窗口(900×650像素)
- 初始化任務列表
- 加載持久化數據
- 構建UI界面
- 居中顯示窗口
4.2 UI布局結構
主窗口采用垂直布局,從上到下包含:
1. 工具欄(操作按鈕):
toolbar = wx.BoxSizer(wx.HORIZONTAL) add_btn = wx.Button(panel, label="添加任務") edit_btn = wx.Button(panel, label="編輯任務") delete_btn = wx.Button(panel, label="刪除任務") toggle_btn = wx.Button(panel, label="切換完成狀態(tài)")
2. 篩選欄:
# 搜索框 self.search_input = wx.TextCtrl(panel, size=(150, -1)) # 分類篩選 self.category_filter = wx.Choice(panel, choices=["全部"]) # 優(yōu)先級篩選 self.priority_filter = wx.Choice(panel, choices=["全部", "高", "中", "低"]) # 狀態(tài)篩選 self.status_filter = wx.Choice(panel, choices=["全部", "未完成", "已完成"])
3. 任務列表:
self.list_ctrl = TodoListCtrl(panel) vbox.Add(self.list_ctrl, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10)
proportion=1:占據剩余所有空間wx.EXPAND:填充水平和垂直方向
4. 統(tǒng)計信息欄:
self.stats_text = wx.StaticText(panel, label="")
4.3 任務管理功能
添加任務:
def on_add_task(self, event):
dlg = TaskDialog(self, "添加任務")
if dlg.ShowModal() == wx.ID_OK:
task_data = dlg.get_task_data()
if task_data['name']:
self.tasks.append(task_data)
self.save_data()
self.refresh_list()
else:
wx.MessageBox("任務名稱不能為空!", "錯誤", wx.OK | wx.ICON_ERROR)
dlg.Destroy()
關鍵步驟:
- 創(chuàng)建并顯示模態(tài)對話框
- 檢查用戶操作(確定/取消)
- 驗證任務名稱非空
- 添加到任務列表
- 保存數據并刷新界面
- 銷毀對話框釋放資源
編輯任務:
def on_edit_task(self, event):
idx = self.list_ctrl.GetFirstSelected()
if idx == -1:
wx.MessageBox("請先選擇要編輯的任務!", "提示", wx.OK | wx.ICON_INFORMATION)
return
task_idx = self.list_ctrl.GetItemData(idx)
task = self.tasks[task_idx]
dlg = TaskDialog(self, "編輯任務", task)
if dlg.ShowModal() == wx.ID_OK:
task_data = dlg.get_task_data()
if task_data['name']:
self.tasks[task_idx] = task_data
self.save_data()
self.refresh_list()
else:
wx.MessageBox("任務名稱不能為空!", "錯誤", wx.OK | wx.ICON_ERROR)
dlg.Destroy()
重要技巧:
- 使用
GetItemData()存儲和獲取任務在原始列表中的索引 - 這樣即使列表經過篩選排序,仍能準確定位任務
刪除任務:
def on_delete_task(self, event):
idx = self.list_ctrl.GetFirstSelected()
if idx == -1:
wx.MessageBox("請先選擇要刪除的任務!", "提示", wx.OK | wx.ICON_INFORMATION)
return
result = wx.MessageBox("確定要刪除選中的任務嗎?", "確認刪除",
wx.YES_NO | wx.ICON_QUESTION)
if result == wx.YES:
task_idx = self.list_ctrl.GetItemData(idx)
del self.tasks[task_idx]
self.save_data()
self.refresh_list()
用戶體驗優(yōu)化:
- 刪除前彈出確認對話框
- 防止誤操作造成數據丟失
切換完成狀態(tài):
def on_toggle_complete(self, event):
idx = self.list_ctrl.GetFirstSelected()
if idx == -1:
wx.MessageBox("請先選擇要操作的任務!", "提示", wx.OK | wx.ICON_INFORMATION)
return
task_idx = self.list_ctrl.GetItemData(idx)
self.tasks[task_idx]['completed'] = not self.tasks[task_idx]['completed']
self.save_data()
self.refresh_list()
4.4 篩選和搜索功能
核心篩選邏輯:
def refresh_list(self):
self.list_ctrl.DeleteAllItems()
# 更新分類篩選列表
self.update_category_filter()
# 獲取篩選條件
search_text = self.search_input.GetValue().lower()
category = self.category_filter.GetStringSelection()
priority = self.priority_filter.GetStringSelection()
status = self.status_filter.GetStringSelection()
filtered_tasks = []
for i, task in enumerate(self.tasks):
# 搜索過濾
if search_text and search_text not in task['name'].lower():
continue
# 分類過濾
if category != "全部" and task.get('category', '') != category:
continue
# 優(yōu)先級過濾
if priority != "全部" and task['priority'] != priority:
continue
# 狀態(tài)過濾
if status == "未完成" and task['completed']:
continue
if status == "已完成" and not task['completed']:
continue
filtered_tasks.append((i, task))
篩選器聯(lián)動:
def update_category_filter(self):
"""動態(tài)更新分類篩選下拉列表"""
current_selection = self.category_filter.GetStringSelection()
# 獲取所有不重復的分類
categories = set()
for task in self.tasks:
cat = task.get('category', '').strip()
if cat:
categories.add(cat)
# 更新下拉列表
category_list = ["全部"] + sorted(list(categories))
self.category_filter.Clear()
self.category_filter.AppendItems(category_list)
# 恢復之前的選擇
if current_selection in category_list:
self.category_filter.SetStringSelection(current_selection)
else:
self.category_filter.SetSelection(0)
智能化設計:
- 自動從任務中提取所有分類
- 去重并排序
- 保持用戶的選擇狀態(tài)
4.5 列表顯示和視覺效果
任務顯示邏輯:
for original_idx, task in filtered_tasks:
index = self.list_ctrl.InsertItem(self.list_ctrl.GetItemCount(),
"?" if task['completed'] else "")
self.list_ctrl.SetItem(index, 1, task.get('name', ''))
self.list_ctrl.SetItem(index, 2, task.get('priority', ''))
self.list_ctrl.SetItem(index, 3, task.get('category', ''))
self.list_ctrl.SetItem(index, 4, task.get('due_date') or '')
created = task.get('created_date', '')
self.list_ctrl.SetItem(index, 5, created.split()[0] if created else '')
self.list_ctrl.SetItemData(index, original_idx)
# 設置顏色
if task['completed']:
self.list_ctrl.SetItemTextColour(index, wx.Colour(150, 150, 150))
elif task['priority'] == "高":
self.list_ctrl.SetItemTextColour(index, wx.Colour(255, 0, 0))
elif task['priority'] == "中":
self.list_ctrl.SetItemTextColour(index, wx.Colour(255, 140, 0))
視覺設計:
- ? 標記已完成任務
- 灰色顯示已完成任務(RGB: 150, 150, 150)
- 紅色顯示高優(yōu)先級任務(RGB: 255, 0, 0)
- 橙色顯示中優(yōu)先級任務(RGB: 255, 140, 0)
- 默認黑色顯示低優(yōu)先級任務
數據關聯(lián)技巧:
self.list_ctrl.SetItemData(index, original_idx)
- 使用
SetItemData存儲原始索引 - 即使列表項順序改變,仍能找到對應的任務數據
4.6 統(tǒng)計信息
def update_stats(self):
total = len(self.tasks)
completed = sum(1 for t in self.tasks if t['completed'])
pending = total - completed
stats = f"總任務: {total} | 已完成: {completed} | 待完成: {pending}"
if total > 0:
percentage = (completed / total) * 100
stats += f" | 完成率: {percentage:.1f}%"
self.stats_text.SetLabel(stats)
統(tǒng)計指標:
- 總任務數
- 已完成數量
- 待完成數量
- 完成率百分比
4.7 數據持久化
保存數據:
def save_data(self):
with open(self.data_file, 'w', encoding='utf-8') as f:
json.dump(self.tasks, f, ensure_ascii=False, indent=2)
關鍵參數:
ensure_ascii=False:支持中文字符indent=2:格式化輸出,便于查看和調試
加載數據:
def load_data(self):
if os.path.exists(self.data_file):
try:
with open(self.data_file, 'r', encoding='utf-8') as f:
self.tasks = json.load(f)
except:
self.tasks = []
容錯處理:
- 檢查文件是否存在
- 使用try-except捕獲解析異常
- 異常時初始化為空列表
技術要點總結
1. wxPython事件系統(tǒng)
wxPython采用事件驅動模型:
# 綁定按鈕點擊事件 add_btn.Bind(wx.EVT_BUTTON, self.on_add_task) # 綁定列表項雙擊事件 self.list_ctrl.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.on_edit_task) # 綁定鍵盤事件 self.Bind(wx.EVT_CHAR_HOOK, self.on_key_press)
事件處理函數簽名:
def on_event(self, event):
# 處理邏輯
pass
2. 布局管理器(Sizer)
wxPython使用Sizer進行布局:
BoxSizer(盒式布局):
vbox = wx.BoxSizer(wx.VERTICAL) # 垂直布局 hbox = wx.BoxSizer(wx.HORIZONTAL) # 水平布局 # 添加控件 vbox.Add(widget, proportion=0, flag=wx.EXPAND, border=10)
參數說明:
proportion:分配剩余空間的比例(0表示不分配)flag:布局標志(wx.EXPAND, wx.ALIGN_CENTER等)border:邊距大小
3. 對話框的使用
模態(tài)對話框:
dlg = TaskDialog(self, "添加任務")
if dlg.ShowModal() == wx.ID_OK:
# 用戶點擊確定
data = dlg.get_task_data()
dlg.Destroy() # 必須銷毀對話框
消息框:
wx.MessageBox("提示信息", "標題", wx.OK | wx.ICON_INFORMATION)
4. ListCtrl的使用技巧
插入項目:
index = list_ctrl.InsertItem(row, "第一列內容") list_ctrl.SetItem(index, 1, "第二列內容") list_ctrl.SetItem(index, 2, "第三列內容")
存儲關聯(lián)數據:
list_ctrl.SetItemData(index, data_id) data_id = list_ctrl.GetItemData(index)
獲取選中項:
idx = list_ctrl.GetFirstSelected()
設置顏色:
list_ctrl.SetItemTextColour(index, wx.Colour(255, 0, 0))
5. 日期控件處理
wxPython日期與Python日期轉換:
# Python date轉wxDateTime
wx_date = wx.DateTime()
wx_date.Set(day, month-1, year) # 注意月份要減1
# wxDateTime轉Python格式
date_str = f"{wx_date.GetYear()}-{wx_date.GetMonth()+1:02d}-{wx_date.GetDay():02d}"
性能優(yōu)化建議
1. 大數據量優(yōu)化
當任務數量超過1000條時,可以考慮:
# 使用虛擬列表(Virtual ListCtrl)
class VirtualTodoListCtrl(wx.ListCtrl):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent,
style=wx.LC_REPORT | wx.LC_VIRTUAL)
def OnGetItemText(self, item, col):
# 動態(tài)返回指定位置的文本
return self.data[item][col]
2. 延遲刷新
# 批量操作時暫停刷新 self.list_ctrl.Freeze() # ... 批量操作 self.list_ctrl.Thaw()
3. 數據庫存儲
對于更大規(guī)模的應用,建議使用SQLite:
import sqlite3
def init_database(self):
conn = sqlite3.connect('tasks.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
priority TEXT,
category TEXT,
due_date TEXT,
completed INTEGER,
created_date TEXT
)
''')
conn.commit()
conn.close()
功能擴展建議
1. 任務提醒功能
import threading
from datetime import datetime, timedelta
def check_reminders(self):
while True:
now = datetime.now()
for task in self.tasks:
if task.get('due_date'):
due = datetime.strptime(task['due_date'], "%Y-%m-%d")
if 0 <= (due - now).days <= 1:
self.show_notification(task)
time.sleep(3600) # 每小時檢查一次
2. 任務導出功能
def export_to_csv(self):
import csv
with open('tasks_export.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=['name', 'priority', 'category', 'due_date', 'completed'])
writer.writeheader()
writer.writerows(self.tasks)
3. 主題切換
class ThemeManager:
THEMES = {
'light': {
'bg': wx.Colour(255, 255, 255),
'fg': wx.Colour(0, 0, 0),
},
'dark': {
'bg': wx.Colour(30, 30, 30),
'fg': wx.Colour(200, 200, 200),
}
}
def apply_theme(self, panel, theme_name):
theme = self.THEMES[theme_name]
panel.SetBackgroundColour(theme['bg'])
panel.SetForegroundColour(theme['fg'])
4. 任務標簽系統(tǒng)
# 為任務添加多個標簽
task_data = {
'name': '項目開發(fā)',
'tags': ['緊急', '重要', '技術'],
# ... 其他字段
}
# 支持按標簽篩選
def filter_by_tags(self, selected_tags):
return [t for t in self.tasks
if any(tag in t.get('tags', []) for tag in selected_tags)]
常見問題解決
1. 中文亂碼問題
# 確保所有文件操作使用UTF-8編碼
with open(file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False)
2. 對話框父窗口問題
# 錯誤:對話框跟隨父窗口最小化 dlg = TaskDialog(self, "添加任務") # 正確:對話框獨立顯示 dlg = TaskDialog(None, "添加任務")
3. ListCtrl刷新閃爍
# 使用Freeze/Thaw減少閃爍 self.list_ctrl.Freeze() self.list_ctrl.DeleteAllItems() # ... 添加項目 self.list_ctrl.Thaw()
4. 日期格式問題
# 統(tǒng)一使用ISO格式
date_str = datetime.now().strftime("%Y-%m-%d")
date_obj = datetime.strptime(date_str, "%Y-%m-%d")
項目部署
1. 打包成可執(zhí)行文件
使用PyInstaller:
pip install pyinstaller pyinstaller --onefile --windowed todolist_app.py
2. 添加圖標
pyinstaller --onefile --windowed --icon=app.ico todolist_app.py
3. 配置文件
創(chuàng)建config.ini:
[Settings] data_file = todolist_data.json window_width = 900 window_height = 650 theme = light
以上就是Python基于wxPython實現(xiàn)TodoList任務管理器開發(fā)詳解的詳細內容,更多關于Python TodoList任務管理器的資料請關注腳本之家其它相關文章!
相關文章
使用python為mysql實現(xiàn)restful接口
這篇文章主要介紹了使用python為mysql實現(xiàn)restful接口的相關資料,需要的朋友可以參考下2018-01-01
python selenium操作cookie的實現(xiàn)
這篇文章主要介紹了python selenium操作cookie的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03
python人工智能tensorflow函數tf.assign使用方法
這篇文章主要為大家介紹了python人工智能tensorflow函數tf.assign使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05

