深度解析如何基于Python實(shí)現(xiàn)文件結(jié)構(gòu)管理工具
在日常開(kāi)發(fā)和項(xiàng)目初始化過(guò)程中,我們經(jīng)常需要按照某種預(yù)設(shè)的架構(gòu)創(chuàng)建大量的文件夾和空文件。特別是當(dāng)我們?cè)谑褂?AI 生成項(xiàng)目方案時(shí),它通常會(huì)給出一個(gè)視覺(jué)化的樹(shù)狀圖(Tree Structure)。手動(dòng)一個(gè)個(gè)新建顯然太慢。
今天,我們將深入分析一個(gè)基于 Python 和 wxPython 編寫的腳本,它不僅能將“文本樹(shù)”瞬間轉(zhuǎn)化為“真實(shí)目錄”,還集成了文件掃描、預(yù)覽和備注管理功能。
背景 (Background)
在軟件開(kāi)發(fā)、學(xué)術(shù)研究或復(fù)雜的文檔管理中,維持一致的文件組織結(jié)構(gòu)至關(guān)重要。常見(jiàn)的痛點(diǎn)包括:
- 重復(fù)勞動(dòng):每次新項(xiàng)目都要手動(dòng)創(chuàng)建
src/,tests/,docs/等目錄。 - 割裂感:AI 或文檔給出了目錄結(jié)構(gòu),但開(kāi)發(fā)者需要“肉眼閱讀”并“手動(dòng)復(fù)現(xiàn)”。
- 文件同步麻煩:每天產(chǎn)生的新文件(如日志、導(dǎo)出的臨時(shí)代碼)需要快速覆蓋到項(xiàng)目對(duì)應(yīng)的占位文件中。
該工具正是在這種“快速落地項(xiàng)目結(jié)構(gòu)”和“日常文件維護(hù)”的需求下誕生的。
目標(biāo) (Goal)
該程序的核心目標(biāo)是打造一個(gè) 輕量級(jí)的桌面效率工具,具體實(shí)現(xiàn)以下功能:
- 文本轉(zhuǎn)目錄:解析 ASCII 樹(shù)狀文本,并在本地磁盤一鍵生成對(duì)應(yīng)的文件夾和文件。
- 可視化管理:通過(guò) GUI 樹(shù)狀控件直觀展示生成的目錄。
- 增量掃描:自動(dòng)識(shí)別計(jì)算機(jī)中“今天”修改過(guò)的非媒體文件,方便快速同步。
- 文件操作集成:支持文件內(nèi)容預(yù)覽、快速覆蓋(Copy2)以及備注記錄。
實(shí)現(xiàn)方法 (Method)
為了實(shí)現(xiàn)上述目標(biāo),開(kāi)發(fā)者采用了以下技術(shù)棧和設(shè)計(jì)模式:
GUI 框架:使用 wxPython。它提供了原生的 Windows/macOS/Linux 控件體驗(yàn),適合開(kāi)發(fā)這類工具類應(yīng)用。
核心邏輯庫(kù):
os&pathlib:處理路徑拼接、目錄創(chuàng)建和文件存在性檢查。shutil:執(zhí)行高保真的文件復(fù)制(保留元數(shù)據(jù))。json:實(shí)現(xiàn)配置的持久化存儲(chǔ),記錄用戶上次選擇的路徑。
解析算法:采用棧(Stack)數(shù)據(jù)結(jié)構(gòu)處理樹(shù)狀結(jié)構(gòu)的深度級(jí)聯(lián)。通過(guò)計(jì)算字符串前綴的空格和符號(hào)數(shù)量來(lái)判斷層級(jí)關(guān)系。
過(guò)程 (Process)
1. 核心解析引擎:從字符串到磁盤
這是程序最精彩的部分(on_create_structure 方法)。它通過(guò)以下步驟處理輸入的文本:
- 符號(hào)清洗:通過(guò)
replace去掉├──,└──,│等裝飾性符號(hào)。 - 層級(jí)推算:利用循環(huán)計(jì)數(shù)每行開(kāi)頭的空格和特殊字符,確定當(dāng)前文件處于第幾層。
- 棧式追蹤:維護(hù)一個(gè)包含
(當(dāng)前路徑, 層級(jí))的棧。當(dāng)新一行的層級(jí)減少時(shí),不斷彈出棧頂,直到找到其父目錄。 - 智能識(shí)別:以
/結(jié)尾的行識(shí)別為文件夾,否則識(shí)別為文件并創(chuàng)建空文件。
2. 界面布局邏輯
程序使用了 wx.BoxSizer 進(jìn)行響應(yīng)式布局。
- 頂部:目標(biāo)路徑選擇。
- 中部:左右分欄。左側(cè)輸入 ASCII 文本,右側(cè)即時(shí)呈現(xiàn)生成的
wx.TreeCtrl樹(shù)狀視圖。 - 底部:集成文件掃描器、預(yù)覽框和剪貼板備注工具。
3. 文件掃描與過(guò)濾機(jī)制
scan_today_files 函數(shù)通過(guò) os.walk 遍歷目錄:
- 時(shí)間過(guò)濾:使用
os.path.getmtime獲取最后修改時(shí)間,并與datetime.now().date()比對(duì)。 - 類型過(guò)濾:定義了
media_extensions集合,自動(dòng)排除圖片、視頻、音頻等大文件,聚焦于腳本和文檔。
結(jié)果 (Results)
通過(guò)運(yùn)行該源代碼,用戶可以獲得一個(gè)功能完備的桌面應(yīng)用:
- 高效初始化:輸入
my_project/ \n ├── main.py \n └── config/,點(diǎn)擊按鈕,磁盤上立即出現(xiàn)對(duì)應(yīng)結(jié)構(gòu)。 - 配置記憶:程序啟動(dòng)時(shí)會(huì)自動(dòng)加載
file_manager_config.json,用戶無(wú)需反復(fù)選擇目標(biāo)文件夾。 - 閉環(huán)操作:用戶可以在左側(cè)看到今天寫了哪些文件,在右側(cè)樹(shù)狀圖中選擇目標(biāo),一鍵“覆蓋”,極大地簡(jiǎn)化了代碼片段或配置文件的同步流程。
- 預(yù)覽與備注:無(wú)需打開(kāi)外部編輯器即可查看文件內(nèi)容,點(diǎn)擊備注即可快速?gòu)?fù)制到剪貼板。
運(yùn)行結(jié)果

完整代碼
import wx
import os
import shutil
import json
from datetime import datetime
from pathlib import Path
class FileStructureManager(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='文件結(jié)構(gòu)管理工具', size=(1200, 800))
self.target_folder = ""
self.tree_root_path = ""
self.created_root_folder = "" # 記錄創(chuàng)建的根文件夾路徑
self.config_file = "file_manager_config.json"
self.last_scan_folder = "" # 記錄上次掃描的文件夾
self.current_file_path = "" # 當(dāng)前預(yù)覽的文件路徑
# 加載配置
self.load_config()
panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
# 目標(biāo)文件夾選擇區(qū)域
folder_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.folder_label = wx.StaticText(panel, label="目標(biāo)文件夾: 未選擇")
folder_btn = wx.Button(panel, label="選擇目標(biāo)文件夾")
folder_btn.Bind(wx.EVT_BUTTON, self.on_select_folder)
folder_sizer.Add(self.folder_label, 1, wx.ALL | wx.EXPAND, 5)
folder_sizer.Add(folder_btn, 0, wx.ALL, 5)
main_sizer.Add(folder_sizer, 0, wx.EXPAND)
# 樹(shù)狀結(jié)構(gòu)輸入?yún)^(qū)域
input_sizer = wx.BoxSizer(wx.HORIZONTAL)
# 左側(cè):Memo輸入框
left_sizer = wx.BoxSizer(wx.VERTICAL)
left_sizer.Add(wx.StaticText(panel, label="輸入樹(shù)狀結(jié)構(gòu):"), 0, wx.ALL, 5)
self.memo = wx.TextCtrl(panel, style=wx.TE_MULTILINE, size=(300, 200))
self.memo.SetValue("excel-sql-ai/\n├── server.js\n├── public/\n│ └── index.html\n├── uploads/\n└── .env")
left_sizer.Add(self.memo, 1, wx.ALL | wx.EXPAND, 5)
create_btn = wx.Button(panel, label="創(chuàng)建文件結(jié)構(gòu)")
create_btn.Bind(wx.EVT_BUTTON, self.on_create_structure)
left_sizer.Add(create_btn, 0, wx.ALL | wx.EXPAND, 5)
input_sizer.Add(left_sizer, 1, wx.EXPAND)
# 右側(cè):Tree組件
right_sizer = wx.BoxSizer(wx.VERTICAL)
right_sizer.Add(wx.StaticText(panel, label="文件結(jié)構(gòu)預(yù)覽:"), 0, wx.ALL, 5)
# --- 新增:加載樹(shù)按鈕 ---
load_tree_btn = wx.Button(panel, label="加載/刷新目錄樹(shù)")
load_tree_btn.Bind(wx.EVT_BUTTON, self.on_load_tree)
right_sizer.Add(load_tree_btn, 0, wx.ALL | wx.EXPAND, 5)
# ----------------------
self.tree = wx.TreeCtrl(panel, size=(300, 200), style=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)
self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.on_tree_select)
right_sizer.Add(self.tree, 1, wx.ALL | wx.EXPAND, 5)
open_btn = wx.Button(panel, label="打開(kāi)根目錄")
open_btn.Bind(wx.EVT_BUTTON, self.on_open_root)
right_sizer.Add(open_btn, 0, wx.ALL | wx.EXPAND, 5)
input_sizer.Add(right_sizer, 1, wx.EXPAND)
main_sizer.Add(input_sizer, 0, wx.EXPAND)
# 文件列表區(qū)域
list_sizer = wx.BoxSizer(wx.HORIZONTAL)
# ListBox1:當(dāng)天非媒體文件
list1_sizer = wx.BoxSizer(wx.VERTICAL)
list1_label_sizer = wx.BoxSizer(wx.HORIZONTAL)
list1_label_sizer.Add(wx.StaticText(panel, label="今日非媒體文件:"), 1, wx.ALL, 5)
scan_btn = wx.Button(panel, label="掃描文件")
scan_btn.Bind(wx.EVT_BUTTON, self.on_scan_files)
list1_label_sizer.Add(scan_btn, 0, wx.ALL, 5)
refresh_btn = wx.Button(panel, label="刷新")
refresh_btn.Bind(wx.EVT_BUTTON, self.on_refresh_scan)
list1_label_sizer.Add(refresh_btn, 0, wx.ALL, 5)
list1_sizer.Add(list1_label_sizer, 0, wx.EXPAND)
self.listbox1 = wx.ListBox(panel, size=(250, 150))
list1_sizer.Add(self.listbox1, 1, wx.ALL | wx.EXPAND, 5)
copy_btn = wx.Button(panel, label="覆蓋")
copy_btn.Bind(wx.EVT_BUTTON, self.on_copy_file)
list1_sizer.Add(copy_btn, 0, wx.ALL | wx.EXPAND, 5)
list_sizer.Add(list1_sizer, 1, wx.EXPAND)
# 中間:預(yù)覽區(qū)域
preview_sizer = wx.BoxSizer(wx.VERTICAL)
preview_label_sizer = wx.BoxSizer(wx.HORIZONTAL)
preview_label_sizer.Add(wx.StaticText(panel, label="文件預(yù)覽:"), 1, wx.ALL, 5)
save_preview_btn = wx.Button(panel, label="保存修改")
save_preview_btn.Bind(wx.EVT_BUTTON, self.on_save_preview)
preview_label_sizer.Add(save_preview_btn, 0, wx.ALL, 5)
preview_sizer.Add(preview_label_sizer, 0, wx.EXPAND)
self.preview = wx.TextCtrl(panel, style=wx.TE_MULTILINE, size=(300, 150))
preview_sizer.Add(self.preview, 1, wx.ALL | wx.EXPAND, 5)
list_sizer.Add(preview_sizer, 1, wx.EXPAND)
# ListBox2:備注列表
list2_sizer = wx.BoxSizer(wx.VERTICAL)
list2_sizer.Add(wx.StaticText(panel, label="備注列表:"), 0, wx.ALL, 5)
edit_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.edit1 = wx.TextCtrl(panel)
submit_btn = wx.Button(panel, label="提交")
submit_btn.Bind(wx.EVT_BUTTON, self.on_submit_note)
edit_sizer.Add(self.edit1, 1, wx.ALL, 5)
edit_sizer.Add(submit_btn, 0, wx.ALL, 5)
list2_sizer.Add(edit_sizer, 0, wx.EXPAND)
self.listbox2 = wx.ListBox(panel, size=(250, 100))
self.listbox2.Bind(wx.EVT_LISTBOX, self.on_note_select)
list2_sizer.Add(self.listbox2, 1, wx.ALL | wx.EXPAND, 5)
list_sizer.Add(list2_sizer, 1, wx.EXPAND)
main_sizer.Add(list_sizer, 1, wx.EXPAND)
# 狀態(tài)欄
self.status = wx.StaticText(panel, label="就緒")
main_sizer.Add(self.status, 0, wx.ALL | wx.EXPAND, 5)
panel.SetSizer(main_sizer)
self.Centre()
self.Show()
def on_load_tree(self, event):
"""點(diǎn)擊加載樹(shù)按鈕的回調(diào)"""
if not self.target_folder:
wx.MessageBox("請(qǐng)先選擇目標(biāo)文件夾", "提示", wx.OK | wx.ICON_WARNING)
return
if not os.path.exists(self.target_folder):
wx.MessageBox("目標(biāo)文件夾路徑不存在,請(qǐng)重新選擇", "錯(cuò)誤", wx.OK | wx.ICON_ERROR)
return
# 如果用戶點(diǎn)擊“加載樹(shù)”,通常是想看整個(gè)目標(biāo)文件夾的內(nèi)容
# 我們可以清除掉“記錄的已創(chuàng)建根目錄”,強(qiáng)制刷新整個(gè)目標(biāo)目錄
self.created_root_folder = ""
self.status.SetLabel(f"正在加載: {self.target_folder}")
self.refresh_tree()
self.status.SetLabel("目錄樹(shù)加載完成")
def load_config(self):
"""加載配置文件"""
try:
if os.path.exists(self.config_file):
with open(self.config_file, 'r', encoding='utf-8') as f:
config = json.load(f)
self.target_folder = config.get('target_folder', '')
self.last_scan_folder = config.get('last_scan_folder', '')
self.created_root_folder = config.get('created_root_folder', '')
except Exception as e:
print(f"加載配置失敗: {e}")
def save_config(self):
"""保存配置文件"""
try:
config = {
'target_folder': self.target_folder,
'last_scan_folder': self.last_scan_folder,
'created_root_folder': self.created_root_folder
}
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(config, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"保存配置失敗: {e}")
def on_select_folder(self, event):
dlg = wx.DirDialog(self, "選擇目標(biāo)文件夾")
if dlg.ShowModal() == wx.ID_OK:
self.target_folder = dlg.GetPath()
self.folder_label.SetLabel(f"目標(biāo)文件夾: {self.target_folder}")
self.status.SetLabel(f"已選擇: {self.target_folder}")
self.save_config() # 保存配置
dlg.Destroy()
def on_create_structure(self, event):
if not self.target_folder:
wx.MessageBox("請(qǐng)先選擇目標(biāo)文件夾", "錯(cuò)誤", wx.OK | wx.ICON_ERROR)
return
text = self.memo.GetValue()
lines = text.split('\n')
try:
# 解析并創(chuàng)建文件結(jié)構(gòu)
stack = [(self.target_folder, -1)] # (路徑, 層級(jí))
root_created = False
self.created_root_folder = "" # 重置創(chuàng)建的根文件夾路徑
for line_num, line in enumerate(lines):
original_line = line
if not line.strip():
continue
# 移除樹(shù)形符號(hào)并獲取文件/文件夾名
clean_line = line
# 移除樹(shù)形字符: ├── └── │ ─
for symbol in ['├──', '└──', '│', '─']:
clean_line = clean_line.replace(symbol, '')
clean_line = clean_line.strip()
if not clean_line:
continue
# 移除注釋部分(# 后面的內(nèi)容)
if '#' in clean_line:
clean_line = clean_line.split('#')[0].strip()
if not clean_line:
continue
# 計(jì)算層級(jí)
level = 0
for char in original_line:
if char in ' │':
level += 1
else:
break
# 如果是第一行且以/結(jié)尾,創(chuàng)建根文件夾
if not root_created and clean_line.endswith('/'):
folder_name = clean_line.rstrip('/')
full_path = os.path.join(self.target_folder, folder_name)
os.makedirs(full_path, exist_ok=True)
stack = [(full_path, 0)]
root_created = True
self.created_root_folder = full_path # 記錄根文件夾
continue
# 根據(jù)層級(jí)找到父目錄
while len(stack) > 1 and stack[-1][1] >= level:
stack.pop()
parent_path = stack[-1][0]
if clean_line.endswith('/'):
# 創(chuàng)建文件夾
folder_name = clean_line.rstrip('/')
full_path = os.path.join(parent_path, folder_name)
os.makedirs(full_path, exist_ok=True)
stack.append((full_path, level))
else:
# 創(chuàng)建文件
full_path = os.path.join(parent_path, clean_line)
dir_path = os.path.dirname(full_path)
if dir_path and not os.path.exists(dir_path):
os.makedirs(dir_path, exist_ok=True)
if not os.path.exists(full_path):
with open(full_path, 'w', encoding='utf-8') as f:
f.write("")
# 刷新樹(shù)形顯示
self.refresh_tree()
self.save_config() # 保存配置
self.status.SetLabel("文件結(jié)構(gòu)創(chuàng)建成功")
wx.MessageBox("文件結(jié)構(gòu)創(chuàng)建成功!", "成功", wx.OK | wx.ICON_INFORMATION)
except Exception as e:
import traceback
error_msg = f"創(chuàng)建失敗: {str(e)}\n\n詳細(xì)信息:\n{traceback.format_exc()}"
wx.MessageBox(error_msg, "錯(cuò)誤", wx.OK | wx.ICON_ERROR)
self.status.SetLabel(f"創(chuàng)建失敗: {str(e)}")
def refresh_tree(self):
self.tree.DeleteAllItems()
root = self.tree.AddRoot("Root")
# 如果有創(chuàng)建的根文件夾,顯示它;否則顯示目標(biāo)文件夾
display_path = self.created_root_folder if self.created_root_folder else self.target_folder
if display_path and os.path.exists(display_path):
self.tree_root_path = display_path
try:
self.add_tree_nodes(root, display_path, depth=0, max_depth=10)
self.tree.ExpandAll() # 展開(kāi)所有節(jié)點(diǎn)以顯示創(chuàng)建的結(jié)構(gòu)
except Exception as e:
self.status.SetLabel(f"刷新樹(shù)失敗: {str(e)}")
def add_tree_nodes(self, parent, path, depth=0, max_depth=10):
# 限制遞歸深度,避免死循環(huán)
if depth >= max_depth:
return
try:
items = sorted(os.listdir(path))
# 限制每層最多顯示100個(gè)項(xiàng)目
if len(items) > 100:
items = items[:100]
for item in items:
full_path = os.path.join(path, item)
# 跳過(guò)隱藏文件和系統(tǒng)文件
if item.startswith('.') and item not in ['.env', '.gitignore']:
continue
try:
node = self.tree.AppendItem(parent, item)
self.tree.SetItemData(node, full_path)
if os.path.isdir(full_path):
# 遞歸添加子節(jié)點(diǎn)
self.add_tree_nodes(node, full_path, depth + 1, max_depth)
except (PermissionError, OSError):
# 跳過(guò)無(wú)權(quán)限訪問(wèn)的文件/文件夾
continue
except (PermissionError, OSError) as e:
# 無(wú)法訪問(wèn)該目錄,跳過(guò)
pass
def on_tree_select(self, event):
item = event.GetItem()
if item:
path = self.tree.GetItemData(item)
if path and os.path.isfile(path):
self.current_file_path = path # 記錄當(dāng)前文件路徑
try:
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read()
self.preview.SetValue(content)
except:
self.preview.SetValue("無(wú)法預(yù)覽此文件")
else:
self.current_file_path = ""
self.preview.SetValue("")
def on_scan_files(self, event):
dlg = wx.DirDialog(self, "選擇要掃描的文件夾")
if dlg.ShowModal() == wx.ID_OK:
folder = dlg.GetPath()
self.last_scan_folder = folder # 記錄最后一次掃描的文件夾
self.save_config() # 保存到配置文件
self.scan_today_files(folder)
dlg.Destroy()
# 修復(fù)缺失的刷新方法
def on_refresh_scan(self, event):
if self.last_scan_folder and os.path.exists(self.last_scan_folder):
self.scan_today_files(self.last_scan_folder)
self.status.SetLabel(f"已刷新掃描: {self.last_scan_folder}")
else:
wx.MessageBox("沒(méi)有記錄上次掃描的文件夾,請(qǐng)先點(diǎn)擊'掃描文件'", "提示")
# 修復(fù)缺失的保存預(yù)覽方法
def on_save_preview(self, event):
if not self.current_file_path:
wx.MessageBox("當(dāng)前沒(méi)有打開(kāi)的文件", "錯(cuò)誤")
return
content = self.preview.GetValue()
try:
with open(self.current_file_path, 'w', encoding='utf-8') as f:
f.write(content)
self.status.SetLabel(f"已保存修改: {os.path.basename(self.current_file_path)}")
wx.MessageBox("文件保存成功!", "成功")
except Exception as e:
wx.MessageBox(f"保存失敗: {str(e)}", "錯(cuò)誤")
def scan_today_files(self, folder):
self.listbox1.Clear()
today = datetime.now().date()
media_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.mp4', '.avi', '.mp3', '.wav', '.mov'}
try:
for root, dirs, files in os.walk(folder):
for file in files:
full_path = os.path.join(root, file)
ext = os.path.splitext(file)[1].lower()
if ext not in media_extensions:
mod_time = datetime.fromtimestamp(os.path.getmtime(full_path)).date()
if mod_time == today:
self.listbox1.Append(full_path)
self.status.SetLabel(f"找到 {self.listbox1.GetCount()} 個(gè)今日文件")
except Exception as e:
wx.MessageBox(f"掃描失敗: {str(e)}", "錯(cuò)誤", wx.OK | wx.ICON_ERROR)
def on_copy_file(self, event):
# 獲取選中的tree文件
tree_item = self.tree.GetSelection()
if not tree_item or not tree_item.IsOk():
wx.MessageBox("請(qǐng)先在樹(shù)中選擇目標(biāo)文件", "提示", wx.OK | wx.ICON_WARNING)
return
target_path = self.tree.GetItemData(tree_item)
if not target_path or os.path.isdir(target_path):
wx.MessageBox("請(qǐng)選擇一個(gè)文件而不是文件夾", "提示", wx.OK | wx.ICON_WARNING)
return
# 獲取選中的源文件
selection = self.listbox1.GetSelection()
if selection == wx.NOT_FOUND:
wx.MessageBox("請(qǐng)先在列表中選擇源文件", "提示", wx.OK | wx.ICON_WARNING)
return
source_path = self.listbox1.GetString(selection)
try:
shutil.copy2(source_path, target_path)
self.status.SetLabel(f"已覆蓋: {os.path.basename(target_path)}")
# 刷新預(yù)覽
with open(target_path, 'r', encoding='utf-8', errors='ignore') as f:
content = f.read(1000)
self.preview.SetValue(content)
except Exception as e:
wx.MessageBox(f"復(fù)制失敗: {str(e)}", "錯(cuò)誤", wx.OK | wx.ICON_ERROR)
def on_open_root(self, event):
open_path = self.created_root_folder if self.created_root_folder else self.tree_root_path
if open_path and os.path.exists(open_path):
if os.name == 'nt': # Windows
os.startfile(open_path)
elif os.name == 'posix': # macOS/Linux
os.system(f'open "{open_path}"' if os.uname().sysname == 'Darwin'
else f'xdg-open "{open_path}"')
else:
wx.MessageBox("根目錄不存在", "錯(cuò)誤", wx.OK | wx.ICON_ERROR)
def on_submit_note(self, event):
note = self.edit1.GetValue()
if note:
self.listbox2.Append(note)
self.edit1.Clear()
self.status.SetLabel("備注已添加")
def on_note_select(self, event):
selection = self.listbox2.GetSelection()
if selection != wx.NOT_FOUND:
text = self.listbox2.GetString(selection)
if wx.TheClipboard.Open():
wx.TheClipboard.SetData(wx.TextDataObject(text))
wx.TheClipboard.Close()
self.status.SetLabel("已復(fù)制到剪貼板")
if __name__ == '__main__':
app = wx.App()
frame = FileStructureManager()
app.MainLoop()
以上就是深度解析如何基于Python實(shí)現(xiàn)文件結(jié)構(gòu)管理工具的詳細(xì)內(nèi)容,更多關(guān)于Python文件結(jié)構(gòu)管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 使用python快速生成nodejs項(xiàng)目文件結(jié)構(gòu)
- python項(xiàng)目文件結(jié)構(gòu)實(shí)例詳解
- Python項(xiàng)目中的文件夾命名和結(jié)構(gòu)設(shè)計(jì)建議最佳實(shí)踐
- Python+PyQt5實(shí)現(xiàn)文件夾結(jié)構(gòu)映射工具
- 使用Python實(shí)現(xiàn)一個(gè)強(qiáng)大的文件系統(tǒng)結(jié)構(gòu)創(chuàng)建器
- 使用Python解析PPT文件并生成JSON結(jié)構(gòu)詳解
- 使用Python創(chuàng)建一個(gè)文件夾結(jié)構(gòu)生成器
- 使用wxPython創(chuàng)建一個(gè)文件夾結(jié)構(gòu)生成器
相關(guān)文章
基于Python輕松制作一個(gè)股票K線圖網(wǎng)站
在當(dāng)今這個(gè)人手一個(gè)?Web?服務(wù)的年代,GUI?程序還是沒(méi)有?Web?服務(wù)來(lái)的香啊。所以本文將用Python制作一個(gè)簡(jiǎn)單的股票K線圖網(wǎng)站,感興趣的可以了解一下2022-09-09
Python中語(yǔ)音轉(zhuǎn)文字相關(guān)庫(kù)介紹(最新推薦)
Python的speech_recognition庫(kù)是一個(gè)用于語(yǔ)音識(shí)別的Python包,它可以使Python程序能夠識(shí)別和翻譯來(lái)自麥克風(fēng)、音頻文件或網(wǎng)絡(luò)流的語(yǔ)音,這篇文章主要介紹了Python中語(yǔ)音轉(zhuǎn)文字相關(guān)庫(kù)介紹,需要的朋友可以參考下2023-05-05
python學(xué)習(xí)教程之socket庫(kù)的基本使用(網(wǎng)絡(luò)編程-套接字)
Python中的socket模塊提供了網(wǎng)絡(luò)編程中的套接字(socket)功能,通過(guò)套接字我們可以實(shí)現(xiàn)不同計(jì)算機(jī)之間的通信,這篇文章主要給大家介紹了關(guān)于python學(xué)習(xí)教程之socket庫(kù)的基本使用,需要的朋友可以參考下2024-07-07
Python生成六萬(wàn)個(gè)隨機(jī),唯一的8位數(shù)字和數(shù)字組成的隨機(jī)字符串實(shí)例
今天小編就為大家分享一篇Python生成六萬(wàn)個(gè)隨機(jī),唯一的8位數(shù)字和數(shù)字組成的隨機(jī)字符串實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
python中常用的各種數(shù)據(jù)庫(kù)操作模塊和連接實(shí)例
這篇文章主要介紹了python中常用的各種數(shù)據(jù)庫(kù)操作模塊和連接實(shí)例,包括sqlite3、oracle、mysql、excel,需要的朋友可以參考下2014-05-05
Python數(shù)據(jù)可視化Pyecharts庫(kù)的使用教程
pyecharts是一個(gè)用于生成echarts圖表的類庫(kù)。echarts是百度開(kāi)源的一個(gè)數(shù)據(jù)可視化庫(kù),用echarts生成的圖可視化效果非常棒。使用pyechart庫(kù)可以在python中生成echarts數(shù)據(jù)圖。本文將詳細(xì)介紹一下Pyecharts庫(kù)的使用,需要的可以參考一下2022-02-02
使用python快速在局域網(wǎng)內(nèi)搭建http傳輸文件服務(wù)的方法
這篇文章主要介紹了使用 python快速在局域網(wǎng)內(nèi)搭建http傳輸文件服務(wù),但是這種方法不要傳輸機(jī)密文件,安全性不高,只用到http協(xié)議沒(méi)有使用任何加密協(xié)議,具體實(shí)現(xiàn)方法跟隨小編一起看看吧2019-11-11

