problems quitting app when wxPython hosting Panda3D

I have been using wxPython to host a Panda3D display window, but have had some difficulties with quitting the application. The following example shows how I have managed to achieve an acceptable program shutdown using release 1.7.0 of Panda3D.

The problem is that using snapshot version 1.7.1 (Panda3D-2010.08.20-108.exe) my code does not shut down properly under Windows XP. Instead we get the old “python.exe has encountered a problem and needs to close. We are sorry for the inconvenience.” message.

Now I am not sure that I am exiting the program in the correct manner, so it may be that I am doing something silly that has stopped working under version 1.7.1, or it may be that something is broken in version 1.7.1.

Is there anyone familiar with wxPython who might be able to look at the following code? As I said, it works using Panda3D 1.7.0 and crashes using Panda3D 1.7.1.

# tested under Panda3D 1.7.0 release
from pandac.PandaModules import loadPrcFileData, WindowProperties
loadPrcFileData('startup', 'window-type none')

from direct.directbase import DirectStart
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import Thread  # necessary for Thread.sleep() which does not exist in threading

import wx
import wx.aui


class MyFrame(wx.Frame):

    def __init__(self, parent, id=-1, title='wx.aui Test',
                 pos=wx.DefaultPosition, size=(800, 600),
                 style=wx.DEFAULT_FRAME_STYLE):
        wx.Frame.__init__(self, parent, id, title, pos, size, style)

        self._mgr = wx.aui.AuiManager(self)

        # create several text controls
        self.pane1 = wx.Window(self, -1, 
                            pos=wx.DefaultPosition, size=wx.Size(200,150),
                            style=wx.NO_BORDER | wx.TE_MULTILINE)

        self.pane2 = wx.TextCtrl(self, -1, 'Pane 2 - sample text',
                            wx.DefaultPosition, wx.Size(200,150),
                            wx.NO_BORDER | wx.TE_MULTILINE)

        self.pane3 = wx.TextCtrl(self, -1, 'Main content window',
                            wx.DefaultPosition, wx.Size(200,150),
                            wx.NO_BORDER | wx.TE_MULTILINE)

        # add the panes to the manager
        self._mgr.AddPane(self.pane1, wx.CENTER, 'Pane Number One')
        self._mgr.AddPane(self.pane2, wx.BOTTOM, 'Pane Number Two')
        self._mgr.AddPane(self.pane3, wx.RIGHT)

        # tell the manager to 'commit' all the changes just made
        self._mgr.Update()

        self.Bind(wx.EVT_CLOSE, self.OnClose)
        
        base.windowType = 'onscreen'
        props = WindowProperties.getDefault()
        props.setOrigin(0,0)
        props.setParentWindow(self.pane1.GetHandle())
        base.openDefaultWindow(props = props)

    def OnClose(self, event):
       self._mgr.UnInit()
       
       Thread.sleep(0.1)     # 
       app.Destroy()         # These four lines of code successfully close the program using
       while app.Pending():  # Panda3D release 1.7.0, but cause a program crash using 
            app.Dispatch()   # Panda3D 1.7.1 snapshot 2010.08.20-108

app = wx.App()
frame = MyFrame(None)
frame.Show()

def handleWxEvents(task): 
    while app.Pending():
        app.Dispatch() 
    return task.cont 

taskMgr.add(handleWxEvents, 'handleWxEvents') 

run()

Hmm, I don’t know. You might try calling base.destroy() in there before you quit. That’s the ShowBase routine that cleans up outstanding Panda hooks.

David

I have tried base.destroy() also base.userExit() and base.exitFunc(), even sys.exit() - none of them actually cause a shutdown when wxPython has got any windows open. As Bob Dylan said: “There must be some way out of here!” but so far I have not found it.

Right, I wouldn’t expect base.destroy() to exit the application, but it should safely clean up Panda prior to exiting via wxPython.

David

Looks like I’ve solved it, and once again it was something stupid I was doing. The following code exits the program gracefully, and as far as I can see cleans up resources properly…

    def OnClose(self, event):
       self._mgr.UnInit()
       app.Destroy()
       base.userExit()

The catch is that it doesn’t exit when the code is running inside PyPE 2.9. That’s a little strange, but so long as it exits when launched as a standalone app then all is well.

Now I have working code and am happy. Back in love with Panda3D!!!