告别Tkinter!用Flet和Python 3.12快速打造一个跨平台桌面待办事项应用
告别Tkinter用Flet和Python 3.12快速打造一个跨平台桌面待办事项应用如果你还在用Tkinter开发Python桌面应用可能会遇到界面老旧、功能有限的问题。而Flet作为新兴的跨平台GUI框架基于Flutter构建能让你用Python代码快速创建现代感十足的应用程序。本文将带你从零开始用Flet构建一个功能完整的待办事项应用涵盖任务添加、完成标记、本地存储等核心功能最终打包为可执行文件。1. 为什么选择Flet替代传统GUI框架在Python生态中Tkinter虽然简单易用但其界面风格停留在上世纪90年代。PyQt功能强大但学习曲线陡峭授权问题也让一些开发者望而却步。Flet的出现为Python开发者提供了新的选择现代UI设计基于Flutter的渲染引擎支持Material Design风格跨平台支持一套代码可运行在Windows、macOS、Linux及Web端开发效率高声明式UI构建方式减少样板代码热重载支持修改代码后实时预览变化# 传统Tkinter vs Flet代码量对比 import tkinter as tk root tk.Tk() label tk.Label(root, textHello Tkinter) label.pack() root.mainloop() import flet as ft def main(page): page.add(ft.Text(Hello Flet)) ft.app(targetmain)2. 开发环境准备与Flet安装2.1 Python环境配置确保使用Python 3.8或更高版本推荐Python 3.12以获得最佳性能python --version # 检查Python版本 pip install --upgrade pip # 更新pip工具2.2 安装Flet及其依赖Flet安装非常简单一条命令即可pip install flet对于Linux用户可能需要额外安装多媒体支持库# Ubuntu/Debian sudo apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev3. 构建待办事项应用核心功能3.1 应用基础框架搭建我们先创建一个基本的应用骨架包含标题和主题设置import flet as ft def main(page: ft.Page): # 配置页面属性 page.title Flet待办事项 page.theme_mode ft.ThemeMode.LIGHT page.horizontal_alignment ft.CrossAxisAlignment.CENTER # 添加应用标题 page.add(ft.Text(我的待办事项, size24, weightft.FontWeight.BOLD)) ft.app(targetmain)3.2 任务添加与显示功能实现使用Column控件作为任务容器TextField和FloatingActionButton实现任务添加def main(page: ft.Page): # ...之前的配置代码... # 任务列表和输入框 tasks ft.Column() new_task ft.TextField(hint_text输入新任务..., expandTrue) def add_task(e): if new_task.value: tasks.controls.append(ft.Checkbox(labelnew_task.value)) new_task.value page.update() # 添加任务输入行 page.add( ft.Row( [new_task, ft.FloatingActionButton(iconft.icons.ADD, on_clickadd_task)], alignmentft.MainAxisAlignment.SPACE_BETWEEN, width400 ) ) # 添加任务列表 page.add(tasks)3.3 任务状态管理与本地存储使用Flet的本地存储API持久化任务数据def main(page: ft.Page): # ...之前的代码... # 加载保存的任务 def load_tasks(): if page.client_storage.contains_key(tasks): saved_tasks page.client_storage.get(tasks) for task in saved_tasks: tasks.controls.append( ft.Checkbox( labeltask[label], valuetask[completed] ) ) # 保存任务到本地存储 def save_tasks(): task_list [ {label: task.label, completed: task.value} for task in tasks.controls ] page.client_storage.set(tasks, task_list) # 修改add_task函数保存数据 def add_task(e): if new_task.value: tasks.controls.append(ft.Checkbox(labelnew_task.value)) new_task.value save_tasks() page.update() # 页面加载时读取任务 page.on_load lambda _: load_tasks()4. 应用界面美化与功能增强4.1 添加任务分类与过滤引入SegmentedButton实现任务分类过滤def main(page: ft.Page): # ...之前的代码... # 任务过滤选项 filter ft.SegmentedButton( selected{all}, options[ ft.Segment(valueall, label全部), ft.Segment(valueactive, label未完成), ft.Segment(valuecompleted, label已完成), ], on_changelambda e: filter_tasks(e.control.selected) ) def filter_tasks(selected): for task in tasks.controls: task.visible ( selected all or (selected active and not task.value) or (selected completed and task.value) ) page.update() # 将过滤器添加到页面 page.add(filter)4.2 添加任务删除功能为每个任务添加删除按钮并实现批量删除已完成任务的功能def main(page: ft.Page): # ...之前的代码... def create_task_view(label): return ft.Row( controls[ ft.Checkbox(labellabel), ft.IconButton( iconft.icons.DELETE_OUTLINE, tooltip删除任务, on_clicklambda e: delete_task(e.control.parent.controls[0]) ) ] ) def delete_task(task): tasks.controls.remove(task) save_tasks() page.update() # 添加清除已完成任务按钮 clear_completed ft.TextButton( text清除已完成, on_clicklambda e: [tasks.controls.remove(task) for task in tasks.controls[:] if task.value] ) page.add(clear_completed)5. 应用打包与分发5.1 使用PyInstaller打包为可执行文件首先安装PyInstallerpip install pyinstaller创建打包脚本build.spec# build.spec block_cipher None a Analysis( [todo_app.py], pathex[], binaries[], datas[], hiddenimports[], hookspath[], hooksconfig{}, runtime_hooks[], excludes[], win_no_prefer_redirectsFalse, win_private_assembliesFalse, cipherblock_cipher, noarchiveFalse, ) pyz PYZ(a.pure, a.zipped_data, cipherblock_cipher) exe EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], nameFletTodo, debugFalse, bootloader_ignore_signalsFalse, stripFalse, upxTrue, upx_exclude[], runtime_tmpdirNone, consoleFalse, disable_windowed_tracebackFalse, argv_emulationFalse, target_archNone, codesign_identityNone, entitlements_fileNone, )执行打包命令pyinstaller --onefile --windowed todo_app.py5.2 跨平台打包注意事项Windows添加--windowed避免显示控制台窗口macOS需要添加应用图标和签名Linux确保依赖库已安装对于更专业的打包需求可以考虑使用flet pack命令flet pack todo_app.py --name Flet待办事项 --icon assets/app_icon.ico6. 性能优化与调试技巧6.1 大型列表性能优化当任务数量较多时使用ListView替代Column提升滚动性能tasks ft.ListView(expandTrue, spacing10)6.2 异步操作处理对于可能耗时的操作使用async/await避免界面卡顿async def save_tasks(): task_list [ {label: task.label, completed: task.value} for task in tasks.controls ] await page.client_storage.set_async(tasks, task_list)6.3 主题定制与暗黑模式添加主题切换按钮支持暗黑模式def toggle_theme(e): page.theme_mode ( ft.ThemeMode.DARK if page.theme_mode ft.ThemeMode.LIGHT else ft.ThemeMode.LIGHT ) page.update() theme_button ft.IconButton( iconft.icons.DARK_MODE, on_clicktoggle_theme, tooltip切换主题 )7. 扩展思路与进阶功能7.1 添加任务优先级标记def create_task_view(label): return ft.Row( controls[ ft.Checkbox(labellabel), ft.Dropdown( options[ ft.dropdown.Option(低), ft.dropdown.Option(中), ft.dropdown.Option(高), ], width100, value中 ), ft.IconButton(iconft.icons.DELETE_OUTLINE) ] )7.2 实现任务拖拽排序def main(page: ft.Page): page.drag_interval 10 # 设置拖拽灵敏度 def on_drag(e: ft.DragUpdateEvent): src e.src dest e.dest if src ! dest: # 交换任务位置 src_idx tasks.controls.index(src) dest_idx tasks.controls.index(dest) tasks.controls[src_idx], tasks.controls[dest_idx] tasks.controls[dest_idx], tasks.controls[src_idx] page.update() tasks ft.Column(on_dragon_drag)7.3 添加任务到期提醒def create_task_view(label): return ft.Row( controls[ ft.Checkbox(labellabel), ft.DatePicker( first_datedatetime.now(), last_datedatetime.now() timedelta(days365), ), ft.IconButton(iconft.icons.DELETE_OUTLINE) ] )在实际项目中我发现Flet的响应式设计特别适合快速原型开发。相比传统GUI框架它能让开发者更专注于业务逻辑而非界面细节。一个实用的建议是对于复杂界面可以先在纸上画出布局草图再转化为Flet的Row/Column组合。