I have a somewhat larger dialog (selecting pictures) and in the constructor there could be an exception which I catch outside and destroy the dialog; now comes heap v stack: with a frame I get the address back and destroy, but with the dialog I don’t get the address right away and I use FindWindowByName; my question is whether there is a simpler way without using names?
I’m not sure I follow what it is you are having problems with or what you are asking. Can you share some of the relevant parts of your code? Or, better yet, create a minimal runnable sample application that demonstrates the problem?
I have made a little example: the console printout shows the correct identical behaviour, the instance is kept for performance and should go away in case of error…
import wx
class Gui(wx.Frame):
def __init__(self):
super().__init__(
None,
title='Demo Exception in __init__',
style=wx.CAPTION | wx.CLOSE_BOX | wx.RESIZE_BORDER)
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
# Frame
vbox.Add(
wx.Button(panel, id=1, label='Frame'),
0, wx.LEFT|wx.TOP|wx.RIGHT, 10)
# Dialog
vbox.Add(
wx.Button(panel, id=2, label='Dialog'),
0, wx.LEFT|wx.TOP|wx.RIGHT, 10)
panel.SetSizerAndFit(vbox)
# event bindings
self.Bind(wx.EVT_CLOSE, self.on_quit)
self.Bind(wx.EVT_BUTTON, self.event_button)
self.sb = self.CreateStatusBar(1, style=wx.SB_FLAT)
self.Show()
def __del__(self):
print(f'id {id(self)} {__class__}: __del__')
def event_button(self, evt):
if (b_id := evt.GetId()) == 1:
if 'frame' not in vars(self):
try:
inst = Frame(self) # get instance of frame
except:
return
else:
self.frame = inst # save instance
elif b_id == 2:
if 'dialog' not in vars(self):
try: # get instance of dialog
inst = Dialog(self)
except:
#++++++++++++++++++++++++++++++++++
self.FindWindowByName('dialog', parent=self).Destroy()
#++++++++++++++++++++++++++++++++++
return
self.dialog = inst # save instance
ret_code = inst.ShowModal()
# do something according to ret_code
def on_quit(self, evt):
self.Destroy()
class Frame(wx.Frame):
def __init__(self, parent):
super().__init__(parent, title='Frame')
print('Init frame')
panel = wx.Panel(self)
# button
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(wx.Button(panel, label='frame button'))
panel.SetSizer(hbox)
# event bindings
self.Bind(wx.EVT_CLOSE, self.on_quit)
self.sb = self.CreateStatusBar(1, style=wx.SB_FLAT)
error = True
if error:
parent.GetStatusBar().SetStatusText('Frame exception')
self.Destroy()
raise RuntimeError("Something bad happened")
else:
self.Show()
def on_quit(self, evt):
self.Destroy()
def __del__(self):
print(f'id {id(self)} {__class__}: __del__')
class Dialog(wx.Dialog):
def __init__(self, parent):
super().__init__(
parent,
title='Dialog',
name='dialog') # name is used for Destroy after init error
print('Init dialouge')
panel = wx.Panel(self)
# button
hbox = wx.BoxSizer(wx.HORIZONTAL)
hbox.Add(wx.Button(panel, label='dialog button'))
panel.SetSizer(hbox)
# event bindings
self.Bind(wx.EVT_CLOSE, self.on_quit)
error = True
if error:
parent.GetStatusBar().SetStatusText('Dialog exception')
raise
def __del__(self):
print(f'id {id(self)} {__class__}: __del__')
def on_quit(self, evt):
self.Destroy()
class WxApp(wx.App):
def __init__(self):
try:
super().__init__(filename=None) # with console
except TypeError:
print('Init error at wxApp')
else:
# set 'English' as language
locale = wx.Locale()
locale.Init(language=wx.LANGUAGE_ENGLISH)
# self.Init() # initialize the inspection tool
frame = Gui()
self.SetTopWindow(frame)
self.MainLoop()
def __del__(self):
print(f'id {id(self)} {__class__}: __del__')
if __name__ == "__main__":
WxApp()
It’s Markdown, so you just need to put code snippet blocks between ```…```
I’ll edit your first code sample message.
You should be able to have the dialog work the same as the frame and destroy itself when encountering the error. For top-level windows the destroy doesn’t actually happen until the next time the pending event queue is empty. So in either case the behavior can be the same.
You are right, it is absolutely symmetrical: something strange must have driven me; I think the ‘Show()’ inside and outside the constructor seduced me… thanks a lot