My wxPython GUI either quits with a Segmentation Fault or fails to quit at all using the standard options. The only successful quit option (no errors) is wx.Exit, which I understand is not a great practice. I've traced the issues down to a few factors, but I'm scratching my head as to why they are having this effect.
Using the wxPython inspector (wx.lib.inspection.InspectionTool()), I've been able to determine that a FigureFrameWxAgg is being created when I run certain pylab functions (pylab.xticks() is the function that creates it here, but I haven't tracked down every single function that has this effect). I don't know what this window is for. It's invisible and doesn't appear to do anything. However, this window totally messes up the shutdown of my GUI. If I use self.Destroy, Python doesn't shut down fully. If I use sys.exit, I get a Segmentation fault. I need to catch the wx.EVT_CLOSE so that I can prompt the user to save his/her work.
Here is the code for a simplified version of the 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()
To add one more level of complexity, the Segmentation Fault with sys.exit() only happens with my brew installed Python. Sys.exit() works fine with Canopy Python.
My questions are: how can I fix this error? And, is using wx.Exit() really so bad?