在开发桌面应用程序时,动态生成用户界面元素并根据配置文件灵活管理是一项常见需求。本文将介绍如何使用Python的wxPython库结合JSON配置文件,开发一个支持动态按钮创建、文件执行和配置管理的桌面应用程序。该应用允许用户通过设置界面配置按钮名称和关联的Python脚本,自动生成按钮并支持脚本执行,同时将配置持久化保存到JSON文件中。
C:\pythoncode\new\output\DynamicButtonRunPy.py
该应用的目标是实现以下功能:
以下是实现该应用的详细步骤和代码解析。
os
、shutil
用于文件操作,subprocess
用于执行Python脚本。项目主要包含以下文件:
main.py
:主程序文件,包含GUI逻辑和核心功能。config.json
:配置文件,存储按钮和路径信息(运行时自动生成)。主窗口(MainFrame
类)包含以下主要组件:
wx.WrapSizer
动态排列按钮。wx.TextCtrl
(多行只读模式)显示Python脚本的源代码。主窗口通过以下步骤初始化:
config.json
配置文件(若不存在则创建默认配置)。代码片段(主窗口初始化):
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="动态按钮程序", size=(800, 600))
self.config = self.load_config()
self.init_ui()
self.load_buttons()
def load_config(self):
try:
with open('config.json', 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
return {'base_path': '', 'buttons': []}
按钮根据config.json
中的buttons
列表动态生成。每个按钮绑定一个点击事件,触发时:
subprocess.run
执行脚本。按钮生成代码:
def load_buttons(self):
self.button_sizer.Clear(True)
for btn_config in self.config.get('buttons', []):
btn = wx.Button(self.button_panel, label=btn_config['name'])
btn.path = btn_config['path']
btn.Bind(wx.EVT_BUTTON, self.on_button_click)
self.button_sizer.Add(btn, 0, wx.ALL, 5)
self.button_panel.Layout()
点击事件处理:
def on_button_click(self, event):
button = event.GetEventObject()
py_path = button.path
try:
with open(py_path, 'r', encoding='utf-8') as f:
self.memo.SetValue(f.read())
except Exception as e:
self.memo.SetValue(f"读取文件失败: {str(e)}")
try:
subprocess.run(['python', py_path], check=True)
except Exception as e:
wx.MessageBox(f"执行文件失败: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
设置窗口(SettingsDialog
类)是一个模态对话框,包含以下组件:
DirBrowseButton
选择初始路径。FileBrowseButton
选择Python脚本。保存逻辑:
config.json
。代码片段(保存逻辑):
def on_save(self, event):
button_name = self.name_input.GetValue()
py_file = self.file_browser.GetValue()
base_path = self.dir_browser.GetValue()
if not all([button_name, py_file, base_path]):
wx.MessageBox("请填写所有字段", "错误", wx.OK | wx.ICON_ERROR)
return
folder_name = os.path.splitext(os.path.basename(py_file))[0]
target_folder = os.path.join(base_path, folder_name)
os.makedirs(target_folder, exist_ok=True)
target_file = os.path.join(target_folder, os.path.basename(py_file))
shutil.copy(py_file, target_file)
if 'buttons' not in self.config:
self.config['buttons'] = []
self.config['base_path'] = base_path
self.config['buttons'].append({
'name': button_name,
'path': target_file,
'folder': target_folder
})
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(self.config, f, ensure_ascii=False, indent=4)
self.EndModal(wx.ID_OK)
config.json
的结构如下:
{
"base_path": "/path/to/base",
"buttons": [
{
"name": "按钮1",
"path": "/path/to/base/script1/script1.py",
"folder": "/path/to/base/script1"
},
{
"name": "按钮2",
"path": "/path/to/base/script2/script2.py",
"folder": "/path/to/base/script2"
}
]
}
配置文件通过json
模块读写,确保支持中文字符(使用ensure_ascii=False
)。
程序入口:
if __name__ == '__main__':
app = wx.App()
frame = MainFrame()
frame.Show()
app.MainLoop()
运行后,主窗口显示动态按钮,点击“选项 -> 设置”打开配置窗口,完成配置后自动更新按钮列表。
main.py
,首次运行会创建空的config.json
。config.json
。