I am trying to understand some Statusbar behavior.
In the below code, if I click" Destroy Statusbar" followed by “Create Statusbar”, my code works as expected.
If I click “Destroy Statusbar” twice in a row, my program abruptly exits. The exception block does not catch any errors.
If I click "Create Statusbar twice in a row, my program reports the following error message.
wx._core.wxAssertionError: C++ assertion “!m_frameStatusBar” failed at …\src\common \framecmn.cpp(381) in wxFrameBase::CreateStatusBar(): recreating status bar in wxFrame
I am using wxPython 4.0.7 post 2, Python 3.6.5, Win 10
Keep in mind that most of wxPython is wrappers around C++ classes, and using the C++ objects incorrectly can result in fatal runtime errors. Lots of those things are caught by C++ assertions that wxPython turns into wxAssertionError exceptions. But not everything can be caught and so we still need to do some defensive programming.
Normally we could use a bool() trick to check if a widget or window still exists or has been destroyed, like:
if widget:
do_something()
But since the statusbar is created by the frame in your example then it doesn’t get the extra wrapper code that makes that possible. However, you can still ask the frame if there is a statusbar or not. Like this:
def destroySB(self, event):
print ("Trying to destroy Statusbar")
try:
if self.GetStatusBar():
self.statusbar.Destroy()
print ("Statusbar destroyed")
else:
print("Statusbar is already gone")
except:
print ("Unable to destory Statusbar")
Thank you for answering my questions and your solution does work.
I am surprised the try/except block was not able to catch the exception when destroying the status bar.
Why does my program abruptly exit if the destroy button in clicked twice in a row? The try/except block did not catch the error.
Why does my program generate an wx.core.wxAssertionError: C++ assertion error is the create button is clocked twice in a row? The try/except block did catch the error.
Robin’s answer was to do some defensive programming by checking if a widget still exists. His solution worked.
I still had a few more questions so I created sample code #2.
This code destroys a button widget multiple times within a try/except block. The code worked as expected, the try/except block did catch the error.
My current questions are:
Why the different behavior between destroying a statusbar and a button?
With respect to using .Destroy(), when should I do some defensive programming as suggested by Robin or make use of try/except code blocks?
Like I said before, since it’s the frame that creates the statusbar in CreateStatusBar instead of creating a wx.StatusBar from Python code, then we are not able to wrap it in the extra code that would catch the attempted use of it after it has been destroyed and turn it into a Python exception.