用 Python 30 分钟做出自己的记事本

张开发
2026/4/20 0:35:45 15 分钟阅读

分享文章

用 Python 30 分钟做出自己的记事本
那天下午我对着电脑屏幕发呆事情是这样的。上周三下午我正写着代码突然需要记点东西。打开系统自带的记事本白底黑字功能倒是够用但总觉得哪里不对劲。我想要个深色背景保护眼睛想把常用短语存成快捷按钮想随手记录的时候自动加上时间戳。打开软件商店搜了一圈免费的要么带广告要么功能臃肿得像个航母。付费的倒是有几个不错的可为了这点小需求花几十块钱总觉得不太划算。我看了眼时间下午三点。离下班还有两个小时。一个念头冒了出来干脆自己写一个。为什么自己写因为真的不难很多人听到“自己做软件”就觉得是件大事要学一堆框架要懂什么设计模式要会各种高深的技术。真不是。Python 写桌面程序比你想的简单得多。标准库里的tkinter就能搞定界面几句话就能搭出一个能用的窗口。加上tkinterdnd2就能支持拖拽文件再加上几行代码就能实现自动保存。我花了大概半小时真的只用了半小时就做出了一个满足日常需求的记事本。整个过程没有复杂的架构设计没有晦涩的框架配置就是写代码跑起来用着爽。今天我就把这个过程完整写出来。你跟着做一遍会发现“自己做软件”这件事门槛比你想象的低得多。第一步搭个能用的窗口打开你的编辑器新建一个 Python 文件就叫my_notepad.py。先把最基本的窗口搭出来。import tkinter as tk from tkinter import scrolledtext, filedialog, messagebox class MyNotepad: def __init__(self): self.root tk.Tk() self.root.title(我的记事本) self.root.geometry(800x600) # 创建文本框 self.text_area scrolledtext.ScrolledText( self.root, wraptk.WORD, font(微软雅黑, 12) ) self.text_area.pack(filltk.BOTH, expandTrue) def run(self): self.root.mainloop() if __name__ __main__: app MyNotepad() app.run()运行一下一个窗口就出来了。中间是可以打字的大框框字体看着舒服窗口大小刚好。这几行代码干了几件事创建了一个窗口加了一个带滚动条的文本框设置好了字体。就这么简单。第二步加上菜单栏空窗口不好看也不实用。把文件菜单加上能新建、打开、保存文件。def __init__(self): # ... 之前的代码 ... # 创建菜单栏 menubar tk.Menu(self.root) self.root.config(menumenubar) # 文件菜单 file_menu tk.Menu(menubar, tearoff0) menubar.add_cascade(label文件, menufile_menu) file_menu.add_command(label新建, commandself.new_file) file_menu.add_command(label打开, commandself.open_file) file_menu.add_command(label保存, commandself.save_file) file_menu.add_separator() file_menu.add_command(label退出, commandself.root.quit) def new_file(self): self.text_area.delete(1.0, tk.END) self.root.title(我的记事本 - 新建文件) def open_file(self): file_path filedialog.askopenfilename( defaultextension.txt, filetypes[(文本文件, *.txt), (所有文件, *.*)] ) if file_path: with open(file_path, r, encodingutf-8) as f: content f.read() self.text_area.delete(1.0, tk.END) self.text_area.insert(1.0, content) self.root.title(f我的记事本 - {file_path}) def save_file(self): file_path filedialog.asksaveasfilename( defaultextension.txt, filetypes[(文本文件, *.txt), (所有文件, *.*)] ) if file_path: content self.text_area.get(1.0, tk.END) with open(file_path, w, encodingutf-8) as f: f.write(content) self.root.title(f我的记事本 - {file_path})现在你有了一个能新建、打开、保存文件的记事本。已经能应对大部分日常记录了。第三步深色模式保护眼睛我是个长期面对屏幕的人对白色背景越来越敏感。深色模式是我最想要的功能。加一个“查看”菜单放一个切换深色模式的选项。def __init__(self): # ... 之前的代码 ... # 查看菜单 view_menu tk.Menu(menubar, tearoff0) menubar.add_cascade(label查看, menuview_menu) view_menu.add_command(label深色模式, commandself.toggle_dark_mode) self.dark_mode False self.default_bg white self.default_fg black def toggle_dark_mode(self): if self.dark_mode: # 切换回浅色模式 self.text_area.config(bgwhite, fgblack, insertbackgroundblack) self.dark_mode False else: # 切换到深色模式 self.text_area.config(bg#1e1e1e, fg#d4d4d4, insertbackgroundwhite) self.dark_mode True点击一下背景变深色文字变成柔和的灰色光标变成白色。晚上写东西眼睛舒服多了。第四步常用短语快捷输入我经常要写一些重复的内容比如“已收到稍后回复”或者“项目进度正常暂无风险”。每次都要重新打烦得很。加一个“工具”菜单里面放几个常用短语的快捷按钮。def __init__(self): # ... 之前的代码 ... # 工具菜单 tools_menu tk.Menu(menubar, tearoff0) menubar.add_cascade(label工具, menutools_menu) tools_menu.add_command(label插入当前时间, commandself.insert_time) tools_menu.add_separator() tools_menu.add_command(label快速回复模板, commandself.insert_reply_template) def insert_time(self): from datetime import datetime now datetime.now().strftime(%Y-%m-%d %H:%M:%S) self.text_area.insert(tk.INSERT, now) def insert_reply_template(self): template 已收到您的消息我会尽快处理并回复您。 self.text_area.insert(tk.INSERT, template)现在写东西的时候点一下“工具-插入当前时间”时间戳自动就出来了。模板内容也能一键插入省了不少事。第五步自动保存再也不怕忘记用系统自带记事本最怕什么写了半天忘了保存电脑突然重启全没了。加个自动保存功能每隔一分钟自动把内容存到备份文件里。import os import pickle def __init__(self): # ... 之前的代码 ... self.backup_file backup.pkl self.load_backup() # 启动自动保存定时器 self.auto_save() def auto_save(self): # 每60秒自动保存一次 content self.text_area.get(1.0, tk.END) with open(self.backup_file, wb) as f: pickle.dump(content, f) self.root.after(60000, self.auto_save) # 60000毫秒 60秒 def load_backup(self): if os.path.exists(self.backup_file): try: with open(self.backup_file, rb) as f: content pickle.load(f) if content.strip(): # 只有非空内容才恢复 self.text_area.insert(1.0, content) except: pass现在你写的东西每隔一分钟自动备份一次。就算程序崩溃或者电脑断电重启后之前的内容还在。第六步拖拽打开文件有时候从文件夹直接拖一个文件到记事本窗口希望它能自动打开。这个功能用tkinterdnd2实现起来很简单。先安装库pip install tkinterdnd2然后修改代码from tkinterdnd2 import DND_FILES, TkinterDnD class MyNotepad: def __init__(self): self.root TkinterDnD.Tk() # 改用支持拖拽的Tk # ... 其他初始化代码 ... # 注册拖拽事件 self.text_area.drop_target_register(DND_FILES) self.text_area.dnd_bind(Drop, self.on_drop) def on_drop(self, event): file_path event.data # 处理拖拽的文件路径 if file_path.startswith({) and file_path.endswith(}): file_path file_path[1:-1] try: with open(file_path, r, encodingutf-8) as f: content f.read() self.text_area.delete(1.0, tk.END) self.text_area.insert(1.0, content) self.root.title(f我的记事本 - {file_path}) except Exception as e: messagebox.showerror(错误, f无法打开文件{e})现在直接从文件夹拖一个 txt 文件到窗口内容就自动加载进来了。第七步打包成exe发给朋友用做好了给自己用当然没问题但如果想分享给不会 Python 的朋友就需要打包成 exe 文件。用pyinstaller打包pip install pyinstaller pyinstaller --onefile --windowed my_notepad.py等一两分钟在dist文件夹里就能找到my_notepad.exe双击就能运行不需要安装 Python。半小时能做什么比你想象的多回到开头那个问题。半小时能做出一款记事本吗从零开始搭窗口用了3分钟加菜单和文件功能用了8分钟深色模式用了3分钟快捷输入用了5分钟自动保存用了6分钟拖拽功能用了5分钟。加起来刚好30分钟。你可能会说这不就是一个简陋的记事本吗系统自带的不是更好系统自带的是够用但自己做的有几个好处想要什么功能就加什么功能。今天想加个字数统计明天想加个云同步后天想加个密码保护全凭自己需求来。没有任何广告和隐私问题。代码全在自己手里不会偷偷上传你的数据不会在角落里塞个广告条。真的很有成就感。这个听起来有点虚但当你用着自己亲手写出来的软件那种感觉确实不太一样。完整代码在这里import tkinter as tk from tkinter import scrolledtext, filedialog, messagebox from tkinterdnd2 import DND_FILES, TkinterDnD import os import pickle from datetime import datetime class MyNotepad: def __init__(self): self.root TkinterDnD.Tk() self.root.title(我的记事本) self.root.geometry(800x600) # 文本框 self.text_area scrolledtext.ScrolledText( self.root, wraptk.WORD, font(微软雅黑, 12) ) self.text_area.pack(filltk.BOTH, expandTrue) # 拖拽支持 self.text_area.drop_target_register(DND_FILES) self.text_area.dnd_bind(Drop, self.on_drop) # 菜单栏 menubar tk.Menu(self.root) self.root.config(menumenubar) # 文件菜单 file_menu tk.Menu(menubar, tearoff0) menubar.add_cascade(label文件, menufile_menu) file_menu.add_command(label新建, commandself.new_file) file_menu.add_command(label打开, commandself.open_file) file_menu.add_command(label保存, commandself.save_file) file_menu.add_separator() file_menu.add_command(label退出, commandself.root.quit) # 查看菜单 view_menu tk.Menu(menubar, tearoff0) menubar.add_cascade(label查看, menuview_menu) view_menu.add_command(label深色模式, commandself.toggle_dark_mode) # 工具菜单 tools_menu tk.Menu(menubar, tearoff0) menubar.add_cascade(label工具, menutools_menu) tools_menu.add_command(label插入当前时间, commandself.insert_time) tools_menu.add_separator() tools_menu.add_command(label快速回复模板, commandself.insert_reply_template) # 状态 self.dark_mode False self.backup_file backup.pkl # 恢复备份 self.load_backup() # 启动自动保存 self.auto_save() def new_file(self): self.text_area.delete(1.0, tk.END) self.root.title(我的记事本 - 新建文件) def open_file(self): file_path filedialog.askopenfilename( defaultextension.txt, filetypes[(文本文件, *.txt), (所有文件, *.*)] ) if file_path: with open(file_path, r, encodingutf-8) as f: content f.read() self.text_area.delete(1.0, tk.END) self.text_area.insert(1.0, content) self.root.title(f我的记事本 - {file_path}) def save_file(self): file_path filedialog.asksaveasfilename( defaultextension.txt, filetypes[(文本文件, *.txt), (所有文件, *.*)] ) if file_path: content self.text_area.get(1.0, tk.END) with open(file_path, w, encodingutf-8) as f: f.write(content) self.root.title(f我的记事本 - {file_path}) def toggle_dark_mode(self): if self.dark_mode: self.text_area.config(bgwhite, fgblack, insertbackgroundblack) self.dark_mode False else: self.text_area.config(bg#1e1e1e, fg#d4d4d4, insertbackgroundwhite) self.dark_mode True def insert_time(self): now datetime.now().strftime(%Y-%m-%d %H:%M:%S) self.text_area.insert(tk.INSERT, now) def insert_reply_template(self): template 已收到您的消息我会尽快处理并回复您。 self.text_area.insert(tk.INSERT, template) def auto_save(self): content self.text_area.get(1.0, tk.END) with open(self.backup_file, wb) as f: pickle.dump(content, f) self.root.after(60000, self.auto_save) def load_backup(self): if os.path.exists(self.backup_file): try: with open(self.backup_file, rb) as f: content pickle.load(f) if content.strip(): self.text_area.insert(1.0, content) except: pass def on_drop(self, event): file_path event.data if file_path.startswith({) and file_path.endswith(}): file_path file_path[1:-1] try: with open(file_path, r, encodingutf-8) as f: content f.read() self.text_area.delete(1.0, tk.END) self.text_area.insert(1.0, content) self.root.title(f我的记事本 - {file_path}) except Exception as e: messagebox.showerror(错误, f无法打开文件{e}) def run(self): self.root.mainloop() if __name__ __main__: app MyNotepad() app.run()把这段代码保存运行你的专属记事本就诞生了。最后说一句技术这东西很多时候不是你不会而是你觉得“这事肯定很复杂”所以一直没动手。等你真的坐下来一行一行敲出来跑起来的那一刻你会发现原来我也能做到。这个记事本只是个起点。你可以继续往上加功能加个加密功能保护隐私加个云同步在多台设备间共享甚至做成一个简单的 Markdown 编辑器。从一个小需求开始亲手把它实现出来这个过程本身就是编程最有趣的部分。

更多文章