这是一个如何将程序状态保存在 JSON 文件中的示例。您已经有一个finish
在程序退出或 Finish 按钮关闭时调用的方法。我们现在可以使用它来调用save
将状态保存到 JSON 文件的方法。
def finish(self, event):
self.save()
self.Destroy()
sys.exit()
def save(self):
windtitle = self.windtitle.GetLabelText()
checkboxes = [{'checked': child.IsChecked(),
'label': child.GetLabel()}
for child in self.panel.GetChildren()
if isinstance(child, wx.CheckBox)]
data = {
'windtitle':windtitle,
'checkboxes':checkboxes,
}
with open(CONFIGFILE, 'w') as f:
json.dump(data, f)
以下是读取 JSON 数据以重构 GUI 的方法:
def load(self):
if os.path.exists(CONFIGFILE):
with open(CONFIGFILE, 'r') as f:
data = json.load(f)
title = data['windtitle']
self.windtitle = wx.StaticText(self.panel, -1, title)
self.vbox.Add(self.windtitle)
for checkbox in data['checkboxes']:
label = checkbox['label']
cb = wx.CheckBox(
self.panel, -1, checkbox['label'])
self.vbox.Add(cb)
cb.SetValue(checkbox['checked'])
else:
self.create_windtitle()
self.create_buttons()
例如:
import wx, sys, os
import json
CONFIGFILE = os.path.expanduser('~/tasklist.json')
class test(wx.Frame):
def __init__(self, parent, id):
frame = wx.Frame.__init__(self, parent, id, 'List', size = (200,500))
self.panel = wx.Panel(self)
self.panelbox = wx.BoxSizer(wx.VERTICAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.load()
self.panelbox.Add(self.vbox)
self.panelbox.Add(self.buttonbox)
self.panel.SetSizer(self.panelbox)
self.panelbox.Fit(self)
self.Bind(wx.EVT_BUTTON, self.addtomenu, self.addButton)
self.Bind(wx.EVT_BUTTON, self.finish, self.finishButton)
self.Bind(wx.EVT_CLOSE, self.finish)
def create_buttons(self):
self.buttonbox = wx.BoxSizer(wx.VERTICAL)
self.addButton = wx.Button(
self.panel, label = "+ Add")
self.finishButton = wx.Button(
self.panel, label = "Finish")
self.buttonbox.Add(self.addButton)
self.buttonbox.Add(self.finishButton)
def create_windtitle(self):
item = wx.TextEntryDialog(None, "List Title")
if item.ShowModal() == wx.ID_OK:
answer = item.GetValue()
self.windtitle = wx.StaticText(self.panel, -1, answer)
self.windtitle.SetForegroundColour("blue")
def addtomenu(self, event):
newitem = wx.TextEntryDialog(None, "New Item")
if newitem.ShowModal() == wx.ID_OK:
if len(self.mylist) > 5:
wx.StaticText(self.panel, -1, "List To Full")
else:
answer = newitem.GetValue()
cb = wx.CheckBox(self.panel, -1, answer)
self.vbox.Add(cb)
self.panelbox.Fit(self)
def finish(self, event):
self.save()
self.Destroy()
sys.exit()
@property
def mylist(self):
return [ child.GetLabel()
for child in self.panel.GetChildren()
if isinstance(child, wx.CheckBox) ]
def save(self):
windtitle = self.windtitle.GetLabelText()
checkboxes = [{'checked': child.IsChecked(),
'label': child.GetLabel()}
for child in self.panel.GetChildren()
if isinstance(child, wx.CheckBox)]
data = {
'windtitle':windtitle,
'checkboxes':checkboxes,
}
with open(CONFIGFILE, 'w') as f:
json.dump(data, f)
def load(self):
if os.path.exists(CONFIGFILE):
with open(CONFIGFILE, 'r') as f:
data = json.load(f)
title = data['windtitle']
self.windtitle = wx.StaticText(self.panel, -1, title)
self.vbox.Add(self.windtitle)
for checkbox in data['checkboxes']:
label = checkbox['label']
cb = wx.CheckBox(
self.panel, -1, checkbox['label'])
self.vbox.Add(cb)
cb.SetValue(checkbox['checked'])
else:
self.create_windtitle()
self.create_buttons()
if __name__ == "__main__":
app = wx.PySimpleApp() #Blood
frame = test(parent = None, id = -1) #Skin
frame.Show()
app.MainLoop() #Heart
顺便说一句,不要使用显式位置来在 GUI 中放置小部件。那条路通向疯狂。如果使用位置(例如pos = (10,yaxis)
),随着 GUI 的增长,修改布局变得越来越困难。每个元素的位置都依赖于其他元素的位置,并且很快变得无法管理。
每个 GUI 框架都提供了一些更明智的方法来实现漂亮的布局。我不是很熟悉wxpython
,但它似乎使用BoxSizers
. 我上面使用的布局非常简陋。我确信通过对 wxpython 布局设计模式的一些研究可以实现更好的布局。
有时我需要找出一个小部件的所有属性和方法是什么。例如,我不知道如何询问 Panel 它包含哪些 Checkboxes。我使用这个函数找到了它:
def describe(obj):
for key in dir(obj):
try:
val = getattr(obj, key)
except AttributeError:
continue
if callable(val):
help(val)
else:
print('{k} => {v}'.format(k = key, v = val))
print('-'*80)
describe(self.panel)
这是我在 utils_debug 中的功能。