WxPython demo: question on the PopupMenu demo

Hi all,

When I looked at the PopupMenu demo in the wxPython demo application I
noticed that the OnContextMenu method which creates the popup menu
destroys the menu at the end.

Is there a special reason why menu.Destroy() needs to be called.
In other words, what would happen if you do not explicitly destroy it?

Best regards,
Tom.

Typically popups and other objects hang around until the last reference to them is removed. Sometime after that they will automatically be destroyed. In the case of a popup, the creating code might not drop its reference until the creating code exits. Explicitly calling menu.Destroy() makes it go away right now.

Tom

···

On Tue, 2009-06-16 at 01:24 -0700, Tom wrote:


Hi all,
When I looked at the PopupMenu demo in the wxPython demo application I
noticed that the OnContextMenu method which creates the popup menu
destroys the menu at the end.
Is there a special reason why menu.Destroy() needs to be called.
In other words, what would happen if you do not explicitly destroy it?
Best regards,
Tom.

Tom,

Hi all,

When I looked at the PopupMenu demo in the wxPython demo application I
noticed that the OnContextMenu method which creates the popup menu
destroys the menu at the end.

Is there a special reason why menu.Destroy() needs to be called.
In other words, what would happen if you do not explicitly destroy it?

Best regards,
Tom.

You should also note that if you don't destroy stuff like this, you
may find that when you close your application, it continues to "run"
in the background, kind of like a zombie process. I've seen this
happen with dialogs that I didn't explicitly destroy.

It's really just good practice to clean up after yourself. Python lets
programmers be lazy in most cases, but since this is a wrapped C++
library, cleaning up sometimes comes as a shock.

Have fun!

Mike

···

On Jun 16, 3:24 am, Tom <tcler...@gmail.com> wrote:

Thanks all.

I suspected it had to do with freeing up resources.
I was a bit surprised though, since I would expect python to clean-up
the memory by its own as soon as there is no reference to the object
anymore.

And indeed, in the first days I've been using wxPython I also
experienced applications that closed, but kept on running in the
background. That was particulary the case when I used a wx.Dialog
without calling the Destroy() method afterwards.... I guess that one
is a common mistake.

Anyway, it doesn't hurt to destroy the object if you're really sure
that it won't be used anymore.

Best regards,
Tom.

···

On Jun 16, 7:36 pm, Mike Driscoll <kyoso...@gmail.com> wrote:

Tom,

On Jun 16, 3:24 am, Tom <tcler...@gmail.com> wrote:

> Hi all,

> When I looked at the PopupMenu demo in the wxPython demo application I
> noticed that the OnContextMenu method which creates the popup menu
> destroys the menu at the end.

> Is there a special reason why menu.Destroy() needs to be called.
> In other words, what would happen if you do not explicitly destroy it?

> Best regards,
> Tom.

You should also note that if you don't destroy stuff like this, you
may find that when you close your application, it continues to "run"
in the background, kind of like a zombie process. I've seen this
happen with dialogs that I didn't explicitly destroy.

It's really just good practice to clean up after yourself. Python lets
programmers be lazy in most cases, but since this is a wrapped C++
library, cleaning up sometimes comes as a shock.

Have fun!

Mike

Tom,

Thanks all.

I suspected it had to do with freeing up resources.
I was a bit surprised though, since I would expect python to clean-up
the memory by its own as soon as there is no reference to the object
anymore.

And indeed, in the first days I've been using wxPython I also
experienced applications that closed, but kept on running in the
background. That was particulary the case when I used a wx.Dialog
without calling the Destroy() method afterwards.... I guess that one
is a common mistake.

Anyway, it doesn't hurt to destroy the object if you're really sure
that it won't be used anymore.

Best regards,
Tom.

Yeah...Python does indeed get rid of most items when the references
hit zero. I don't know how to explain why Dialogs can become zombies,
but I think it has something to do with them being designed to be
reused. Thus when you just close them, wx expects that you'll have
them be reused later and keeps a reference to them handy for when that
happens.

My guess is that the popup behaves similarly. The toolkit thinks
you'll use it again later, so it saves a reference. Anyway, Robin or
Tim R. can probably explain it better than I can.

- Mike

···

On Jun 17, 4:02 am, Tom <tcler...@gmail.com> wrote:

Tom wrote:

Hi all,

When I looked at the PopupMenu demo in the wxPython demo application I
noticed that the OnContextMenu method which creates the popup menu
destroys the menu at the end.

Is there a special reason why menu.Destroy() needs to be called.
In other words, what would happen if you do not explicitly destroy it?

To expand a little on what others have said, the need to call Destroy revolves around C++ object ownership. Normally a wx.Menu is owned by the menubar or parent menu that it is attached to, and since the menubar is owned by the frame and since frames Destroy() themselves when they are closed, then when the frame is destroyed then everything it owns, including the menubar and the menus, is destroyed too and we don't have to worry about managing that cleanup from wxPython. The same approach works for all the child windows too, they are owned by their parent window.

But a menu used for a popup menu is not owned by anything else, so the above rule breaks down a bit. The Pythonic thing to do is to make it act like the C++ object is owned by the Python proxy object, then when the proxy is destroyed the C++ menu object will be too. Unfortunately since most wx C++ objects hold a reference to their Python proxy (to be able to implement some of the other wxPython magic) that wouldn't work since there would be a reference cycle that couldn't be broken by the garbage collector since one of the references is held by a C++ object. (Plus, I was using this approach long before Python even had a cyclic garbage collector.) So that means that you need to call Destroy yourself so the C++ object will go away and then since it decref's its reference then the Python proxy object goes away too.

Dialogs also fall into this same pattern because the C++ object does not automatically destroy itself when it is closed like frames do. This is because the typical use case for dialogs is that you access values from its widgets after ShowModal has returned. So because of the extra reference on the C++ side you need to call Destroy for every dialog yourself.

···

--
Robin Dunn
Software Craftsman

Crystal clear.
Thanks Robin.

Regards,
Tom.

···

On Jun 17, 10:25 pm, Robin Dunn <ro...@alldunn.com> wrote:

Tom wrote:
> Hi all,

> When I looked at the PopupMenu demo in the wxPython demo application I
> noticed that the OnContextMenu method which creates the popup menu
> destroys the menu at the end.

> Is there a special reason why menu.Destroy() needs to be called.
> In other words, what would happen if you do not explicitly destroy it?

To expand a little on what others have said, the need to call Destroy
revolves around C++ object ownership. Normally a wx.Menu is owned by
the menubar or parent menu that it is attached to, and since the menubar
is owned by the frame and since frames Destroy() themselves when they
are closed, then when the frame is destroyed then everything it owns,
including the menubar and the menus, is destroyed too and we don't have
to worry about managing that cleanup from wxPython. The same approach
works for all the child windows too, they are owned by their parent window.

But a menu used for a popup menu is not owned by anything else, so the
above rule breaks down a bit. The Pythonic thing to do is to make it
act like the C++ object is owned by the Python proxy object, then when
the proxy is destroyed the C++ menu object will be too. Unfortunately
since most wx C++ objects hold a reference to their Python proxy (to be
able to implement some of the other wxPython magic) that wouldn't work
since there would be a reference cycle that couldn't be broken by the
garbage collector since one of the references is held by a C++ object.
(Plus, I was using this approach long before Python even had a cyclic
garbage collector.) So that means that you need to call Destroy
yourself so the C++ object will go away and then since it decref's its
reference then the Python proxy object goes away too.

Dialogs also fall into this same pattern because the C++ object does not
automatically destroy itself when it is closed like frames do. This is
because the typical use case for dialogs is that you access values from
its widgets after ShowModal has returned. So because of the extra
reference on the C++ side you need to call Destroy for every dialog
yourself.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org