From: John H. <jdh...@ac...> - 2005-04-11 14:45:40
|
OK, I spent some time looking at this morning and think I have a fix that works for matplotlib wx API users as well as pylab users. For the record, a little background. The module matplotlib.backends.backend_wx contains all the classes to enable matplotlib to be embedded in a wx application. There are two modes this module is used in: application developers who want to control the wx windows, panels, frames, etc, themselves, and pylab users who want a matlab like environment in which all the figure window, creation, etc, is managed for them. To support the latter, all the matplotlib GUI backends are required to define two functions new_figure_manager - creates a new wxFrame show - realizes/shows all frames Jeremy O'Donoghue, who wrote the wx backend, and latter Matt Newville who has been helping maintain it of late, tried putting the wxapp instantiation in the show function, but this caused a segfault on some platforms with some versions of wxpython (win32 with 2.4.x). We never figured out the root cause of this since often times the person developing/maintaining wx didn't have access to the buggy combination of platform + version. So we left wxapp creation at the module level which was ugly, hacky, and buggy, but at least it didn't seg fault. Today I spent some time tracking down where and why the segfault was occurring, and it was new_figure_manager -> FigureFrameWx -> wxPanel.__init__ The call to wxPanel.__init__ trigged the segfault. It appears the cause of this problem is that the wxapp must be created before the wxPanel is init'ed. The solution is to put the wxapp creation in new_figure_manager, not show, so that the app will be created before the wxpanel. This appears to work. Here is what I am currently doing wxapp = None # module level def new_figure_manager(num, *args, **kwargs): global wxapp if wxapp is None: wxapp = wx.PySimpleApp() wxapp.SetExitOnFrameDelete(True) ...snipsnip... def show(): ...snipsnip... if show._needmain and not matplotlib.is_interactive(): if wxapp is not None: wxapp.MainLoop() show._needmain = False And this seems to work for pylab and wx apps. Since apps will never call new_figure_manager or show, there should be no problem If there is a better / more elegant / more wxlike way to do this, let me know. Thanks, JDH |