我的 wxPython GUI 要么因段错误而退出,要么使用标准选项根本无法退出。唯一成功的退出选项(没有错误)是 wx.Exit,我知道这不是一个很好的做法。我已将问题归结为几个因素,但我对它们为何产生这种影响感到摸不着头脑。
使用wxPython检查器(wx.lib.inspection.InspectionTool()),我已经能够确定当我运行某些pylab函数时正在创建一个FigureFrameWxAgg(pylab.xticks()是创建它的函数)在这里,但我还没有追踪到具有此效果的每个函数)。我不知道这个窗口是做什么用的。它是看不见的并且似乎没有做任何事情。然而,这个窗口完全搞乱了我的 GUI 的关闭。如果我使用 self.Destroy,Python 不会完全关闭。如果我使用 sys.exit,则会出现段错误。我需要捕获 wx.EVT_CLOSE 以便我可以提示用户保存他/她的工作。
以下是简化版 GUI 的代码:
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
import wx
import wx.grid
import wx.lib.scrolledpanel
import wx.lib.inspection
import sys
import pylab
class my_frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Many Rows')
self.InitUI()
def InitUI(self):
self.panel = wx.Window(self, size=(200, 200))
hbox_all= wx.BoxSizer(wx.HORIZONTAL)
self.create_menubar()
self.fig1 = pylab.Figure((5, 5), dpi=100)
self.canvas1 = FigCanvas(self.panel, -1, self.fig1)
self.fig1.text(0.01,0.98,"Arai plot",{'family':'Arial', 'fontsize':10, 'style':'normal','va':'center', 'ha':'left' })
self.araiplot = self.fig1.add_axes([0.1,0.1,0.8,0.8])
self.araiplot.clear()
self.araiplot.plot(range(5),range(5),lw=0.75,clip_on=False)
xt = pylab.xticks()
grid = wx.grid.Grid(self.panel)
grid.ClearGrid()
grid.CreateGrid(100, 100)
grid.AutoSize()
hbox_all.AddSpacer(self.canvas1)
hbox_all.AddSpacer(20)
hbox_all.AddSpacer(grid)
hbox_all.AddSpacer(20)
self.panel.SetSizer(hbox_all)
hbox_all.Fit(self)
self.Centre()
self.Show()
def create_menubar(self):
"""
Create menu bar
"""
self.menubar = wx.MenuBar()
menu_file = wx.Menu()
menu_file.AppendSeparator()
m_exit = menu_file.Append(wx.ID_EXIT, "Quit", "Quit application")
self.Bind(wx.EVT_CLOSE, self.on_menu_exit)
self.menubar.Append(menu_file, "&File")
self.SetMenuBar(self.menubar)
def on_menu_exit(self, event):
self.Destroy() # this doesn't quit Python fully, unless I comment out 'matplotlib.use('WXAgg')'
#for w in wx.GetTopLevelWindows():
# if w.Title == 'Figure 1':
# w.Destroy() # if I pre-destroy the FigureFrameWxAgg window, I get a PyDeadObjectError when I run self.Destroy
# self.Destroy() #
# wx.Exit() # forces the program to exit, with no clean up. works, but not an ideal solution
#sys.exit() # program closes, but with segmentation error
#self.Close() # creates infinite recursion error, because we have a binding to wx.EVT_CLOSE
if __name__ == '__main__':
app = wx.PySimpleApp(redirect=False)
app.frame = my_frame()
if '-i' in sys.argv:
wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
为了增加一层复杂性,sys.exit() 的段错误仅发生在我安装了 Brew 的 Python 上。 Sys.exit() 与 Canopy Python 配合良好。
我的问题是:如何修复此错误?而且,使用 wx.Exit() 真的那么糟糕吗?
最佳答案
您的示例存在几个问题:
不要在 GUI 应用程序中使用 pylab,因为它带有自己的主循环(当 wxPython 主循环退出时,它不会退出)。你必须杀死 pylab。
# both not required # matplotlib.use('WXAgg') # import pylab # use instead from matplotlib.figure import Figure ... def __init__(# ... ... self.fig1 = Figure((5, 5), dpi=100)
您的菜单项“关闭”不起作用(至少在 Windows 上不起作用)。
wx.ID_EXIT
用于对话框中的按钮。不要问我哪些预定义 ID 是用于菜单的。ID_QUIT = wx.NewId() menu_file.Append(ID_QUIT , "Quit", "Quit application") # self.Bind(wx.EVT_MENU, self.on_quit, id=ID_QUIT) def on_quit(self, evt): self.Close()
在这种情况下,没有必要绑定(bind)到
wx.EVT_CLOSE
。如果你想在关闭事件上做一些事情,你必须跳过它。当你跳过它时,wxPython会自己处理它。self.Bind(wx.EVT_CLOSE, self.on_close) ... def on_close(self, evt): # you can veto the close here or perform cleanup evt.Skip()
如果您相应地更改代码,wxPython 将正确关闭所有内容。
关于python - wxPython无法退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28103710/