Python-在重新启动之间保存程序的状态?
我想知道如何保存程序的当前设置,以便在程序重新启动或计算机重新启动时保持不变,除非另有规定。例如,windows默认程序“便笺”,用于保存文本,以便即使在计算机关闭后也可以使用 是否有某种类型的模块可以导入?我的程序基本上是一个任务列表程序,您可以在其中向列表中添加内容,并使用wxPython复选框勾选它。是否有任何可能的方法可以在程序退出后保持其状态 如果有人能用我的代码给我看一个例子,我将不胜感激,别担心,我不会只是简单地复制它,然后完成它。这将被视为我的一次学习经历,以便我将来可以使用它。谢谢 这是我的节目:Python-在重新启动之间保存程序的状态?,python,wxpython,save,restart,Python,Wxpython,Save,Restart,我想知道如何保存程序的当前设置,以便在程序重新启动或计算机重新启动时保持不变,除非另有规定。例如,windows默认程序“便笺”,用于保存文本,以便即使在计算机关闭后也可以使用 是否有某种类型的模块可以导入?我的程序基本上是一个任务列表程序,您可以在其中向列表中添加内容,并使用wxPython复选框勾选它。是否有任何可能的方法可以在程序退出后保持其状态 如果有人能用我的代码给我看一个例子,我将不胜感激,别担心,我不会只是简单地复制它,然后完成它。这将被视为我的一次学习经历,以便我将来可以使用它。
import wx, sys,os
mylist = []
class test(wx.Frame):
def __init__(self, parent, id):
self.count = 1
#Frame
wx.Frame.__init__(self,parent,id,'List',size = (200,500))
#Panel
self.panel = wx.Panel(self)
item = wx.TextEntryDialog(None, "List Title")
if item.ShowModal() == wx.ID_OK:
print 'here'
answer = item.GetValue()
mylist.append(answer)
print mylist
windtitle = wx.StaticText(self.panel, -1, answer, (10,10))
windtitle.SetForegroundColour("blue")
addButton = wx.Button(self.panel, label = "+ Add", pos=(40,450), size = (60,-1))
finishButton = wx.Button(self.panel, label = "Finish", pos=(110,450), size = (60,-1))
self.Bind(wx.EVT_BUTTON, self.addtomenu, addButton)
self.Bind(wx.EVT_BUTTON, self.finish, finishButton)
def finish(self, event):
self.Destroy()
sys.exit()
def addtomenu(self,event):
newitem = wx.TextEntryDialog(None, "New Item")
if newitem.ShowModal() == wx.ID_OK:
count = len(mylist)+1
print count
yaxis = 20*count
if count == 21:
wx.StaticText(self.panel, -1, "List To Full", (10, yaxis))
else:
answer = newitem.GetValue()
mylist.append(answer)
print mylist
self.Bind(wx.EVT_CLOSE, self.closewindow)
wx.CheckBox(self.panel, -1, answer, (10,yaxis), size = (200,-1))
def closewindow(self, event):
self.Destroy()
if __name__ == "__main__":
app=wx.PySimpleApp() #Blood
frame = test(parent=None, id = -1) #Skin
frame.Show()
app.MainLoop() #Heart
您可能希望将按钮的状态存储在数据集合(如列表或dict)中,然后可以封送或序列化数据 e、 g 稍后,只需将json重新加载回程序中,并通过在dict上循环来设置按钮 e、 g 您可以使用或一些人可能会建议,但是
json
可能是更好的选择
使用您的代码,您可能希望执行以下操作
json.dump(mylist, output)
当然,在我的示例中,这里是一个如何将程序状态保存在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布局设计模式的研究,可以获得更好的布局
有时我需要找出小部件的所有属性和方法。例如,我不知道如何询问面板包含哪些复选框。我用这个函数找到它:
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中使用的函数。请稍等。我想知道是否有一个内在的解决方案——毕竟,我们大多数人迟早会面临这个问题 事实证明,有一种叫做的东西可以用来简单地保存和恢复状态
注意,我并没有使用它,只是偶然发现。我所有的按钮都已经存储在一个列表中,所以基本上只需编写一些程序来查看该列表并将其转换为复选框?这似乎是个好主意,但是这个json模块是什么?我应该如何存储这个列表,以便在计算机关闭时保存它?我对python相当陌生。@user1952975您想要存储的按钮是什么?我已经上传了我的代码,正如您所看到的,目前它非常简单。我将如何在代码中实现您所说的内容?很抱歉,我上次的评论是“输入”而不是“按钮”:DThanks,我现在就去试试。@Jokob我遇到了一个错误,考虑到我对json这整件事还不熟悉,我有点不知所措。我理解json save是您要求它保存到file.json中的内容。然后,您可以使用您展示的示例调用它,但是我得到一个错误:mylist=json.loads(fp),它表示它需要一个字符串…:c请帮助可能有一个特定于wxpython的应用程序析构函数。谢谢,这是我在wxpython中的第一个程序,我只是想弄明白。我知道Tkinter中有.pack()函数,我希望wxpython中也有类似的功能。我当然会查看Boxsizer,查看您的代码,看看它是如何工作的,再次感谢:)还有这个模块utils_debug,我如何获得它?在过去的10分钟里我一直在搜索,但在上面什么也找不到。我没有这个模块。你可以删除utils\u debug——我发布的代码中没有用到它。你在网上找不到它。然而,我编辑了我的帖子,展示了我如何使用它的
descripe
功能来搜索小部件属性。我喜欢“血”、“皮”、“心”的评论——非常可爱。
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
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)