使用Python編寫一個(gè)自己的記事本
那天下午,我對(duì)著電腦屏幕發(fā)呆
事情是這樣的。
上周三下午,我正寫著代碼,突然需要記點(diǎn)東西。打開系統(tǒng)自帶的記事本,白底黑字,功能倒是夠用,但總覺得哪里不對(duì)勁。我想要個(gè)深色背景保護(hù)眼睛,想把常用短語存成快捷按鈕,想隨手記錄的時(shí)候自動(dòng)加上時(shí)間戳。
打開軟件商店搜了一圈,免費(fèi)的要么帶廣告,要么功能臃腫得像個(gè)航母。付費(fèi)的倒是有幾個(gè)不錯(cuò)的,可為了這點(diǎn)小需求花幾十塊錢,總覺得不太劃算。
我看了眼時(shí)間,下午三點(diǎn)。離下班還有兩個(gè)小時(shí)。
一個(gè)念頭冒了出來:干脆自己寫一個(gè)。
為什么自己寫?因?yàn)檎娴牟浑y
很多人聽到“自己做軟件”就覺得是件大事,要學(xué)一堆框架,要懂什么設(shè)計(jì)模式,要會(huì)各種高深的技術(shù)。
真不是。
Python 寫桌面程序,比你想的簡(jiǎn)單得多。標(biāo)準(zhǔn)庫(kù)里的 tkinter 就能搞定界面,幾句話就能搭出一個(gè)能用的窗口。加上 tkinterdnd2 就能支持拖拽文件,再加上幾行代碼就能實(shí)現(xiàn)自動(dòng)保存。
我花了大概半小時(shí),真的只用了半小時(shí),就做出了一個(gè)滿足日常需求的記事本。
整個(gè)過程沒有復(fù)雜的架構(gòu)設(shè)計(jì),沒有晦澀的框架配置,就是寫代碼,跑起來,用著爽。
今天我就把這個(gè)過程完整寫出來。你跟著做一遍,會(huì)發(fā)現(xiàn)“自己做軟件”這件事,門檻比你想象的低得多。
第一步:搭個(gè)能用的窗口
打開你的編輯器,新建一個(gè) 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")
# 創(chuàng)建文本框
self.text_area = scrolledtext.ScrolledText(
self.root,
wrap=tk.WORD,
font=("微軟雅黑", 12)
)
self.text_area.pack(fill=tk.BOTH, expand=True)
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = MyNotepad()
app.run()
運(yùn)行一下,一個(gè)窗口就出來了。中間是可以打字的大框框,字體看著舒服,窗口大小剛好。
這幾行代碼干了幾件事:創(chuàng)建了一個(gè)窗口,加了一個(gè)帶滾動(dòng)條的文本框,設(shè)置好了字體。就這么簡(jiǎn)單。
第二步:加上菜單欄
空窗口不好看,也不實(shí)用。把文件菜單加上,能新建、打開、保存文件。
def __init__(self):
# ... 之前的代碼 ...
# 創(chuàng)建菜單欄
menubar = tk.Menu(self.root)
self.root.config(menu=menubar)
# 文件菜單
file_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="文件", menu=file_menu)
file_menu.add_command(label="新建", command=self.new_file)
file_menu.add_command(label="打開", command=self.open_file)
file_menu.add_command(label="保存", command=self.save_file)
file_menu.add_separator()
file_menu.add_command(label="退出", command=self.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", encoding="utf-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", encoding="utf-8") as f:
f.write(content)
self.root.title(f"我的記事本 - {file_path}")
現(xiàn)在你有了一個(gè)能新建、打開、保存文件的記事本。已經(jīng)能應(yīng)對(duì)大部分日常記錄了。
第三步:深色模式,保護(hù)眼睛
我是個(gè)長(zhǎng)期面對(duì)屏幕的人,對(duì)白色背景越來越敏感。深色模式是我最想要的功能。
加一個(gè)“查看”菜單,放一個(gè)切換深色模式的選項(xiàng)。
def __init__(self):
# ... 之前的代碼 ...
# 查看菜單
view_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="查看", menu=view_menu)
view_menu.add_command(label="深色模式", command=self.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(bg="white", fg="black", insertbackground="black")
self.dark_mode = False
else:
# 切換到深色模式
self.text_area.config(bg="#1e1e1e", fg="#d4d4d4", insertbackground="white")
self.dark_mode = True
點(diǎn)擊一下,背景變深色,文字變成柔和的灰色,光標(biāo)變成白色。晚上寫東西眼睛舒服多了。
第四步:常用短語快捷輸入
我經(jīng)常要寫一些重復(fù)的內(nèi)容,比如“已收到,稍后回復(fù)”或者“項(xiàng)目進(jìn)度正常,暫無風(fēng)險(xiǎn)”。每次都要重新打,煩得很。
加一個(gè)“工具”菜單,里面放幾個(gè)常用短語的快捷按鈕。
def __init__(self):
# ... 之前的代碼 ...
# 工具菜單
tools_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="工具", menu=tools_menu)
tools_menu.add_command(label="插入當(dāng)前時(shí)間", command=self.insert_time)
tools_menu.add_separator()
tools_menu.add_command(label="快速回復(fù)模板", command=self.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 = "已收到您的消息,我會(huì)盡快處理并回復(fù)您。"
self.text_area.insert(tk.INSERT, template)
現(xiàn)在寫東西的時(shí)候,點(diǎn)一下“工具-插入當(dāng)前時(shí)間”,時(shí)間戳自動(dòng)就出來了。模板內(nèi)容也能一鍵插入,省了不少事。
第五步:自動(dòng)保存,再也不怕忘記
用系統(tǒng)自帶記事本最怕什么?寫了半天忘了保存,電腦突然重啟,全沒了。
加個(gè)自動(dòng)保存功能,每隔一分鐘自動(dòng)把內(nèi)容存到備份文件里。
import os
import pickle
def __init__(self):
# ... 之前的代碼 ...
self.backup_file = "backup.pkl"
self.load_backup()
# 啟動(dòng)自動(dòng)保存定時(shí)器
self.auto_save()
def auto_save(self):
# 每60秒自動(dòng)保存一次
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(): # 只有非空內(nèi)容才恢復(fù)
self.text_area.insert(1.0, content)
except:
pass
現(xiàn)在你寫的東西每隔一分鐘自動(dòng)備份一次。就算程序崩潰或者電腦斷電,重啟后之前的內(nèi)容還在。
第六步:拖拽打開文件
有時(shí)候從文件夾直接拖一個(gè)文件到記事本窗口,希望它能自動(dòng)打開。這個(gè)功能用 tkinterdnd2 實(shí)現(xiàn)起來很簡(jiǎn)單。
先安裝庫(kù):
pip install tkinterdnd2
然后修改代碼:
from tkinterdnd2 import DND_FILES, TkinterDnD
class MyNotepad:
def __init__(self):
self.root = TkinterDnD.Tk() # 改用支持拖拽的Tk
# ... 其他初始化代碼 ...
# 注冊(cè)拖拽事件
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", encoding="utf-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("錯(cuò)誤", f"無法打開文件:{e}")
現(xiàn)在直接從文件夾拖一個(gè) txt 文件到窗口,內(nèi)容就自動(dòng)加載進(jìn)來了。
第七步:打包成exe,發(fā)給朋友用
做好了給自己用當(dāng)然沒問題,但如果想分享給不會(huì) Python 的朋友,就需要打包成 exe 文件。
用 pyinstaller 打包:
pip install pyinstaller pyinstaller --onefile --windowed my_notepad.py
等一兩分鐘,在 dist 文件夾里就能找到 my_notepad.exe,雙擊就能運(yùn)行,不需要安裝 Python。
半小時(shí)能做什么?比你想象的多
回到開頭那個(gè)問題。半小時(shí)能做出一款記事本嗎?
從零開始,搭窗口用了3分鐘,加菜單和文件功能用了8分鐘,深色模式用了3分鐘,快捷輸入用了5分鐘,自動(dòng)保存用了6分鐘,拖拽功能用了5分鐘。加起來剛好30分鐘。
你可能會(huì)說:這不就是一個(gè)簡(jiǎn)陋的記事本嗎,系統(tǒng)自帶的不是更好?
系統(tǒng)自帶的是夠用,但自己做的有幾個(gè)好處:
想要什么功能就加什么功能。今天想加個(gè)字?jǐn)?shù)統(tǒng)計(jì),明天想加個(gè)云同步,后天想加個(gè)密碼保護(hù),全憑自己需求來。
沒有任何廣告和隱私問題。代碼全在自己手里,不會(huì)偷偷上傳你的數(shù)據(jù),不會(huì)在角落里塞個(gè)廣告條。
真的很有成就感。這個(gè)聽起來有點(diǎn)虛,但當(dāng)你用著自己親手寫出來的軟件,那種感覺確實(shí)不太一樣。
完整代碼在這里
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,
wrap=tk.WORD,
font=("微軟雅黑", 12)
)
self.text_area.pack(fill=tk.BOTH, expand=True)
# 拖拽支持
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(menu=menubar)
# 文件菜單
file_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="文件", menu=file_menu)
file_menu.add_command(label="新建", command=self.new_file)
file_menu.add_command(label="打開", command=self.open_file)
file_menu.add_command(label="保存", command=self.save_file)
file_menu.add_separator()
file_menu.add_command(label="退出", command=self.root.quit)
# 查看菜單
view_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="查看", menu=view_menu)
view_menu.add_command(label="深色模式", command=self.toggle_dark_mode)
# 工具菜單
tools_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="工具", menu=tools_menu)
tools_menu.add_command(label="插入當(dāng)前時(shí)間", command=self.insert_time)
tools_menu.add_separator()
tools_menu.add_command(label="快速回復(fù)模板", command=self.insert_reply_template)
# 狀態(tài)
self.dark_mode = False
self.backup_file = "backup.pkl"
# 恢復(fù)備份
self.load_backup()
# 啟動(dòng)自動(dòng)保存
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", encoding="utf-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", encoding="utf-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(bg="white", fg="black", insertbackground="black")
self.dark_mode = False
else:
self.text_area.config(bg="#1e1e1e", fg="#d4d4d4", insertbackground="white")
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 = "已收到您的消息,我會(huì)盡快處理并回復(fù)您。"
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", encoding="utf-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("錯(cuò)誤", f"無法打開文件:{e}")
def run(self):
self.root.mainloop()
if __name__ == "__main__":
app = MyNotepad()
app.run()
把這段代碼保存,運(yùn)行,你的專屬記事本就誕生了。
最后說一句
技術(shù)這東西,很多時(shí)候不是你不會(huì),而是你覺得“這事肯定很復(fù)雜”所以一直沒動(dòng)手。
等你真的坐下來,一行一行敲出來,跑起來的那一刻,你會(huì)發(fā)現(xiàn):原來我也能做到。
這個(gè)記事本只是個(gè)起點(diǎn)。你可以繼續(xù)往上加功能:加個(gè)加密功能保護(hù)隱私,加個(gè)云同步在多臺(tái)設(shè)備間共享,甚至做成一個(gè)簡(jiǎn)單的 Markdown 編輯器。
從一個(gè)小需求開始,親手把它實(shí)現(xiàn)出來,這個(gè)過程本身就是編程最有趣的部分。
以上就是使用Python編寫一個(gè)自己的記事本的詳細(xì)內(nèi)容,更多關(guān)于Python記事本的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python使用datetime模塊處理日期時(shí)間及常用功能詳解
datetime模塊是Python標(biāo)準(zhǔn)庫(kù)中用于處理日期和時(shí)間的模塊,在本節(jié)中,我們將介紹datetime模塊的一些常用功能,并通過實(shí)例代碼詳細(xì)講解每個(gè)知識(shí)點(diǎn),有需要的朋友可以借鑒參考下,希望能夠有所幫助2023-06-06
淺談Pycharm中的Python Console與Terminal
今天小編就為大家分享一篇淺談Pycharm中的Python Console與Terminal,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01
一個(gè)檢測(cè)OpenSSL心臟出血漏洞的Python腳本分享
這篇文章主要介紹了一個(gè)檢測(cè)OpenSSL心臟出血漏洞的Python腳本,心臟出血漏洞是互聯(lián)網(wǎng)上的地震,看到的同學(xué)趕緊升級(jí)OpenSSL,避免黑客入侵2014-04-04
python如何通過實(shí)例方法名字調(diào)用方法
這篇文章主要為大家詳細(xì)介紹了python如何通過實(shí)例方法名字調(diào)用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
Python實(shí)現(xiàn)復(fù)制和移動(dòng)Excel工作表并保留所有格式
在使用 Python 操作 Excel 文件時(shí),可能會(huì)遇到需要在同一個(gè)工作簿內(nèi)或不同工作簿之間復(fù)制或移動(dòng)工作表的情況,本文將介紹如何使用 Python 復(fù)制和移動(dòng) Excel 工作表,希望對(duì)大家有所幫助2025-11-11
Python與機(jī)器學(xué)習(xí)庫(kù)LightGBM使用詳解
LightGBM是一種高效的梯度提升決策樹框架,以其快速訓(xùn)練和高預(yù)測(cè)性能聞名,它通過直方圖算法和基于葉子生長(zhǎng)策略優(yōu)化技術(shù),能夠在大規(guī)模數(shù)據(jù)集上提供卓越性能,本文詳細(xì)介紹了如何使用LightGBM進(jìn)行分類和回歸任務(wù),包括模型構(gòu)建、參數(shù)調(diào)整2025-01-01
Pandas中DataFrame.replace()函數(shù)的實(shí)現(xiàn)
DataFrame.replace()用于替換DataFrame中的指定值,本文主要介紹了Pandas中DataFrame.replace()函數(shù)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07

