重置 wxPython 应用程序/销毁所有内容并从初始框架开始
Resetting a wxPython app / destroying everything and starting from initial frame
我在这里阅读了其他答案,但它们似乎都涉及完全关闭应用程序,确保所有进程和框架等都在此过程中被销毁。我想做的有点不同。
我的应用程序包含三个框架(StartFrame、ParaFrame、ResultFrame)以及一个用于存储和操作数据的自定义 class。基础知识是: StartFrame 只是一些文本和一个“开始”按钮。 “开始”创建一个 ParaFrame 实例,隐藏 StartFrame,并显示 ParaFrame 实例。 Paraframe 有一堆小部件供用户 select 文件以及如何分析它。输入所有字段后,弹出“分析”按钮,(单击时)实例化自定义 DataHandler class,根据用户 selections 设置其参数,调用 DataHandler 方法分析数据,隐藏自身,并实例化+显示 ResultsFrame。毫不奇怪,ResultsFrame 显示了分析结果。
我想添加一个“重新开始”控件,它会破坏所有内容(所有框架、面板、DataHandler 实例等)并显示新的 StartFrame 实例,否则会破坏所有内容 除了 已实例化但隐藏的 StartFrame,再次显示该帧,但我不知所措。
简化示例如下:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(900,600),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
self.frm2 = ParaFrame(None)
self.Hide()
self.frm2.Show()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(950,800),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
self.resfrm = ResultFrame(self, dhandler.data, dhandler.data2)
self.Hide()
self.resfrm.Show()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="results", size=(1535,935))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm.frm2.Destroy()
frm.Show()
def main():
import wx.lib.mixins.inspection
app = wx.App()
frm = StartFrame(None)
frm.Show()
wx.lib.inspection.InspectionTool().Show(refreshTree=True)
app.MainLoop()
if __name__ == "__main__":
main()
如您所见,在 ResultFrame 中我有一个“重新开始”按钮绑定到一个方法,在该方法中我尝试使用 [= 销毁 ParaFrame 实例(以及由此产生的 DataHandler 和 ResultFrame 实例) 12=],却报错:
Traceback (most recent call last):
File "C:\Python\Scripts\stackexchange code.py", line 102, in OnRestart
frm.frm2.Destroy()
NameError: name 'frm' is not defined
如果我将行更改为 frm2.Destroy()
,我会得到同样的错误,但会显示 name 'frm2' is not defined
.
我在这里做错了什么,我怎样才能实现我的目标?我对 OOP 还是很陌生,对 wxPython 也很陌生,所以我很感激任何帮助。我想要的只是让该按钮销毁所有内容并再次显示 the/an 初始 StartFrame。谢谢:)
只要您创建的每个 class 都没有父级,您就可以在创建链中的下一帧后使用 self.Destroy()
,而不会破坏任何 children
。 (将所需的任何数据作为父参数以外的参数传递)
所以你的代码看起来像这样:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
frm2 = ParaFrame(None)
frm2.Show()
self.Destroy()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
resfrm = ResultFrame(None, dhandler.data, dhandler.data2)
resfrm.Show()
self.Destroy()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="Results", size=(900,600))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm = StartFrame(None)
frm.Show()
self.Destroy()
def main():
app = wx.App()
frm = StartFrame(None)
frm.Show()
app.MainLoop()
if __name__ == "__main__":
main()
我在这里阅读了其他答案,但它们似乎都涉及完全关闭应用程序,确保所有进程和框架等都在此过程中被销毁。我想做的有点不同。
我的应用程序包含三个框架(StartFrame、ParaFrame、ResultFrame)以及一个用于存储和操作数据的自定义 class。基础知识是: StartFrame 只是一些文本和一个“开始”按钮。 “开始”创建一个 ParaFrame 实例,隐藏 StartFrame,并显示 ParaFrame 实例。 Paraframe 有一堆小部件供用户 select 文件以及如何分析它。输入所有字段后,弹出“分析”按钮,(单击时)实例化自定义 DataHandler class,根据用户 selections 设置其参数,调用 DataHandler 方法分析数据,隐藏自身,并实例化+显示 ResultsFrame。毫不奇怪,ResultsFrame 显示了分析结果。
我想添加一个“重新开始”控件,它会破坏所有内容(所有框架、面板、DataHandler 实例等)并显示新的 StartFrame 实例,否则会破坏所有内容 除了 已实例化但隐藏的 StartFrame,再次显示该帧,但我不知所措。
简化示例如下:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(900,600),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
self.frm2 = ParaFrame(None)
self.Hide()
self.frm2.Show()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="LOD Calculator", size=wx.Size(950,800),
style=wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.RESIZE_BORDER|wx.TAB_TRAVERSAL)
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
self.resfrm = ResultFrame(self, dhandler.data, dhandler.data2)
self.Hide()
self.resfrm.Show()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="results", size=(1535,935))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm.frm2.Destroy()
frm.Show()
def main():
import wx.lib.mixins.inspection
app = wx.App()
frm = StartFrame(None)
frm.Show()
wx.lib.inspection.InspectionTool().Show(refreshTree=True)
app.MainLoop()
if __name__ == "__main__":
main()
如您所见,在 ResultFrame 中我有一个“重新开始”按钮绑定到一个方法,在该方法中我尝试使用 [= 销毁 ParaFrame 实例(以及由此产生的 DataHandler 和 ResultFrame 实例) 12=],却报错:
Traceback (most recent call last):
File "C:\Python\Scripts\stackexchange code.py", line 102, in OnRestart
frm.frm2.Destroy()
NameError: name 'frm' is not defined
如果我将行更改为 frm2.Destroy()
,我会得到同样的错误,但会显示 name 'frm2' is not defined
.
我在这里做错了什么,我怎样才能实现我的目标?我对 OOP 还是很陌生,对 wxPython 也很陌生,所以我很感激任何帮助。我想要的只是让该按钮销毁所有内容并再次显示 the/an 初始 StartFrame。谢谢:)
只要您创建的每个 class 都没有父级,您就可以在创建链中的下一帧后使用 self.Destroy()
,而不会破坏任何 children
。 (将所需的任何数据作为父参数以外的参数传递)
所以你的代码看起来像这样:
import wx
class StartFrame(wx.Frame):
"""App start frame"""
FRAME_MIN_SIZE = (900,600)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.startpnl = wx.Panel(self)
self.startvsizer=wx.BoxSizer(wx.VERTICAL)
self.startbtnsizer=wx.BoxSizer(wx.HORIZONTAL)
self.btn = wx.Button(self.startpnl, wx.ID_ANY, "Start Analysis",\
size = (200,60))
self.btn.Bind(wx.EVT_BUTTON, self._OnStart)
self.startbtnsizer.AddStretchSpacer()
self.startbtnsizer.Add(self.btn, 0, wx.CENTER)
self.startbtnsizer.AddStretchSpacer()
self.startvsizer.AddStretchSpacer()
self.startvsizer.Add(self.startbtnsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.startvsizer.AddStretchSpacer()
self.startpnl.SetSizerAndFit(self.startvsizer)
def _OnStart(self,event):
frm2 = ParaFrame(None)
frm2.Show()
self.Destroy()
class ParaFrame(wx.Frame):
"""Data load frame"""
FRAME_MIN_SIZE = (950,800)
def __init__(self, parent):
wx.Frame.__init__(self, parent=parent,
id=wx.ID_ANY, title="Load Calculator", size=wx.Size(900,600))
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.analyzebtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Analyze",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.analyzebtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.analyzebtn.Bind(wx.EVT_BUTTON, self._analyze)
def _analyze(self, event):
dhandler = DataHandler(self)
dhandler.data = "a bunch"
dhandler.data2 = " of data"
dhandler.data3 = " goes here"
dhandler._analyzeData()
resfrm = ResultFrame(None, dhandler.data, dhandler.data2)
resfrm.Show()
self.Destroy()
class DataHandler:
def __init__(self,parent):
self.data = ''
self.data2 = ''
self.data3 = ''
def _analyzeData(self):
anastr = self.data + self.data2 + " gets analyzed"
print(anastr)
class ResultFrame(wx.Frame):
def __init__(self, parent, targets, dftables):
super(ResultFrame, self).__init__(parent, title="Results", size=(900,600))
self.targets = targets
self.dftables = dftables
self.InitUI()
self.Layout()
def InitUI(self):
self.mainpnl = wx.Panel(self)
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.vsizer = wx.BoxSizer(wx.VERTICAL)
self.restartbtn = wx.Button(self.mainpnl, wx.ID_ANY, u"Start Over",\
wx.DefaultPosition, wx.DefaultSize, 0)
self.vsizer.AddStretchSpacer()
self.vsizer.Add(self.restartbtn, 0, wx.ALL, 10)
self.vsizer.AddStretchSpacer()
self.mainsizer.AddStretchSpacer()
self.mainsizer.Add(self.vsizer, wx.SizerFlags().Expand().Border(wx.ALL, 25))
self.mainsizer.AddStretchSpacer()
self.mainpnl.SetSizerAndFit(self.mainsizer)
self.restartbtn.Bind(wx.EVT_BUTTON, self.OnRestart)
### this is where I try to destroy the ParaFrame instance and everything spawned by it, unsuccessfully
def OnRestart(self, event):
frm = StartFrame(None)
frm.Show()
self.Destroy()
def main():
app = wx.App()
frm = StartFrame(None)
frm.Show()
app.MainLoop()
if __name__ == "__main__":
main()