3

The package wxPython is very good for developing GUI-interface applications in Python, but so far, the only methods that I have found to exit from an application developed in wxPython launched from the Python command line always generate a runtime error when the application is closed programmatically. For example, the method Frame.Destroy() generates the error:

Runtime error 
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\PythonSamples\ArcGIS Examples\TIGER Data Loader.py", line 522, in 
<module>
    frame.Destroy()
RuntimeError: wrapped C/C++ object of type Frame has been deleted

A similar error message is generated if Frame.Close() is called. The only way that I have found to close an application window generated by wxPython WITHOUT generating a run-time error is by deleting the wx.App object:

app=wx.App()
frame = wx.Frame(etc....)
.
.
.

and somewhere in the program where you want to exit the Frame window, you issue

del app

This seems like a bad way to terminate an application. Is there a better way that does NOT generate a run-time error message?

JDMorganArkansas
  • 123
  • 2
  • 10

2 Answers2

3

calling frame.Destroy() in an event deletes the frame, but the program then returns to the wx mainloop.

When the mainloop finds that the frame has been destroyed, the error occurs.

Instead (like when using threads), use wx.CallAfter so wx it is executed in the main thread and somewhere where wx expects such changes. For you:

wx.CallAfter(frame.Destroy)

note as suggested in comments that it's cleaner to do:

wx.CallAfter(frame.Close)

because it gives your app a chance to call some cleanup code, unlike Destroy

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 1
    You can use any of wxPython's thread-safe methods: `wx.CallAfter`, `wx.PostEvent` or `wx.CallLater`. And `wx.Close` is the recommended way of closing a frame. You usually don't use `Destroy` except for dialogs or when you are catching `wx.EVT_CLOSE` – Mike Driscoll Mar 23 '18 at 21:16
  • that was an empiric answer, based on code that we've developped. OP seems to state that `wx.Close` also generates run time error. I didn't test this but you seem to advise `wx.CallAfter(frame.Close)`. Why not? – Jean-François Fabre Mar 23 '18 at 21:38
  • My understanding of `self.Close` is that it calls `self.Destroy` eventually. The reason you do not want to call it yourself is if you have custom teardown code that you want executed when `self.Close` fires `wx.EVT_CLOSE`, which you can catch. Then you do the teardown. If you call `self.Destroy`, then you do not have an opportunity to catch the close event, so you can't do any special teardown code. – Mike Driscoll Mar 26 '18 at 19:48
  • @MikeDriscoll probably. I didn't need teardown, neither did the OP. I'll suggest the alternative, which should work, provided it's wrapped in `wx.CallAfter`. Damn! wx is soooo active :) I edited. looks nice isn't it ? – Jean-François Fabre Mar 26 '18 at 19:54
1

How about frame.Close() ? Docs are here

For reference, the following code doesn't spit out any error on my machine:

import wx

class MyFrame(wx.Frame):

    def __init__(self):
        super().__init__(None, title="Close Me")
        panel = wx.Panel(self)

        closeBtn = wx.Button(panel, label="Close")
        closeBtn.Bind(wx.EVT_BUTTON, self.onClose)

    def onClose(self, event):
        self.Close()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    frame.Show()
    app.MainLoop()
Jacques Gaudin
  • 15,779
  • 10
  • 54
  • 75
  • The wx.App object doesn't have a Close() method. It does have a __del__() method, however. I don't know, but I assume that it has the same effect as the del app statement. I'm just not sure what kind of cleanup is done if the wx.App object is deleted. – JDMorganArkansas Mar 23 '18 at 16:59
  • Sorry I meant `frame.Close()`. I think the duplicate link should help you in figuring out. – Jacques Gaudin Mar 23 '18 at 17:05
  • By the way the `__del__` method is a generic method that gets called when you call `del(app)`. https://stackoverflow.com/questions/1481488/what-is-the-del-method-how-to-call-it – Jacques Gaudin Mar 23 '18 at 17:07
  • 1
    Just a note, `self.Destroy()` will achieve the same result ,in this example, as `self.Close()` – Rolf of Saxony Mar 23 '18 at 17:51