Modal Dialogs portability

Hi,

today I noticed something funny.
My app creates modal dialogs.

A snippet of the class __init__ for a modal (custom) dialog would be

class Dialog(wx.Dialog):
  def __init__(self):
    # stuff omitted here
     self.CentreOnParent()
    self.ShowModal()

  def close(self,event):
    self.EndModal()
    self.Destroy()

The caller would do

dlg=DialogClass(params)
if dlg.GetReturnCode():
  something here

this will block until the dialogclass goes into the close method.
Funny thing though: On GTK (not GTK2, didn't test that) the above code works,
specially the self.Destroy() in the close method. The dlg is still around on
GTK, even after the explicit destroy.
On win32 however it obviously isn't always (sometimes it is, sometimes not and
I get an assert exception - PyDeadObject....)

So here the question: I don't want to do the ShowModal() and Destroy in the
caller, I'd rather have the dialog take care of itself. If I wouldn't do the
self.Destroy() and I deleted the reference kept in "dlg" in the caller, will
the dialog be destroyed automatically (no more references to it) ? Or do I
have to do an explicit Destroy() to get rid of it ?

Thx

  UC

···

--
Open Source Solutions 4U, LLC 2570 Fleetwood Drive
Phone: +1 650 872 2425 San Bruno, CA 94066
Cell: +1 650 302 2405 United States
Fax: +1 650 872 2417

There may be a better way to handle this, but the way I do it is to create
my own class that does NOT subclass wxDialog, but rather creates and holds a
reference to a wxDialog instance in an instance variable. My code looks
something like this:

class MyDialog:
  def __init__(self, parent):
    self.dlg = wxDialog(parent, (other args as nec))

  def getInput(self):
        val = self.dlg.ShowModal()
        self.dlg.Destroy()
        return val

Then the calling program would use code like this:

  value = MyDialog(self).getInput()

This calling code would show the dialog box to the user who would eventually
close it. At that point, the MyDialog object would destroy the dialog box
(i.e., the wxDialog instance) and pass the desired value to the user. As
soon as the MyDialog obj passes out of scope, it is garbage collected.

Paul Gardella
BBN Technologies

···

-----Original Message-----
From: Uwe C. Schroeder [mailto:uwe@oss4u.com]
Sent: Monday, September 29, 2003 10:48 PM
To: wxPython-users@lists.wxwindows.org
Subject: [wxPython-users] Modal Dialogs portability

Hi,

today I noticed something funny.
My app creates modal dialogs.

A snippet of the class __init__ for a modal (custom) dialog would be

class Dialog(wx.Dialog):
  def __init__(self):
    # stuff omitted here
     self.CentreOnParent()
    self.ShowModal()

  def close(self,event):
    self.EndModal()
    self.Destroy()

The caller would do

dlg=DialogClass(params)
if dlg.GetReturnCode():
  something here

this will block until the dialogclass goes into the close method.
Funny thing though: On GTK (not GTK2, didn't test that) the above code
works,
specially the self.Destroy() in the close method. The dlg is still around on
GTK, even after the explicit destroy.
On win32 however it obviously isn't always (sometimes it is, sometimes not
and
I get an assert exception - PyDeadObject....)

So here the question: I don't want to do the ShowModal() and Destroy in the
caller, I'd rather have the dialog take care of itself. If I wouldn't do the
self.Destroy() and I deleted the reference kept in "dlg" in the caller, will
the dialog be destroyed automatically (no more references to it) ? Or do I
have to do an explicit Destroy() to get rid of it ?

Thx

  UC

--
Open Source Solutions 4U, LLC 2570 Fleetwood Drive
Phone: +1 650 872 2425 San Bruno, CA 94066
Cell: +1 650 302 2405 United States
Fax: +1 650 872 2417

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org

Uwe C. Schroeder wrote:

Hi,

today I noticed something funny.
My app creates modal dialogs.

A snippet of the class __init__ for a modal (custom) dialog would be

class Dialog(wx.Dialog):
  def __init__(self):
    # stuff omitted here
     self.CentreOnParent()
    self.ShowModal()

  def close(self,event):
    self.EndModal()
    self.Destroy()

The caller would do

dlg=DialogClass(params)
if dlg.GetReturnCode():
  something here

this will block until the dialogclass goes into the close method.
Funny thing though: On GTK (not GTK2, didn't test that) the above code works, specially the self.Destroy() in the close method. The dlg is still around on GTK, even after the explicit destroy.
On win32 however it obviously isn't always (sometimes it is, sometimes not and I get an assert exception - PyDeadObject....)

For the top level windows Destroy() does not immediately delete the C++ instance, but instead adds it to a list of pending delete objects. The next time idle events are processed windows in that list will be deleted. (This is done to ensure that there are no more events pending for the window.) So if you don't do anything that could cause idle events to be processed then the dialog instance will still exist, but I wouldn't count on that behaviour.

So here the question: I don't want to do the ShowModal() and Destroy in the caller, I'd rather have the dialog take care of itself. If I wouldn't do the self.Destroy() and I deleted the reference kept in "dlg" in the caller, will the dialog be destroyed automatically (no more references to it) ? Or do I have to do an explicit Destroy() to get rid of it ?

You do need to do the Destroy(). I've explained why in the past so I won't go into it again other than to say that it has to be done.

Another approach that you could do is to put a function wrapper around your dialogs that creates, shows and destroys the dialog and then returns a results object. There are some function wrappers for the common dialogs in in wxPython/lib/dialogs.py, for example:

def colourDialog(parent=None, colourData=None, colour=None):
     if colourData:
         dialog = wx.wxColourDialog(parent, colourData)
     else:
         dialog = wx.wxColourDialog(parent)
         dialog.GetColourData().SetChooseFull(1)
     if colour is not None:
         dialog.GetColourData().SetColour(color)
     result = DialogResults(dialog.ShowModal())
     result.colourData = dialog.GetColourData()
     result.colour = result.colourData.GetColour().Get()
     dialog.Destroy()
     return result

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!