-
Notifications
You must be signed in to change notification settings - Fork 558
Description
Operating system: Ubuntu 24.04.3 LTS
wxPython version & source: '4.2.3 gtk3 (phoenix) wxWidgets 3.2.7'
Python version & source: Python 3.12.3 (main, Jan 8 2026, 11:30:50) [GCC 13.3.0] on linux
I'm running this on Linux but also reproduced the issue on my Windows machine. I believe it's running the same version of wxPython
Description of the problem:
Calling Remove on a submenu and attempting to re-add it or interact with it in any way is giving an error: RuntimeError: wrapped C/C++ object of type Menu has been deleted. The below program illustrates the issue. Click on the 'Add' button, then 'Remove', then 'Add' again. The buttons are necessary because the deletion appears to happen sometime after Remove() is called, not as part of the call to remove. I don't think this could be Python's GC because it should still have a reference to the submenu.
The documentation for Remove explicitly states "doesn’t delete the associated C++ object.", so I'm pretty sure this is a bug. I haven't tried it with other menu items.
Code Example (click to expand)
#!/usr/bin/env python3
import wx
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((400, 300))
self.SetTitle("frame")
self.attached = False
# Menu Bar
self.frame_menubar = wx.MenuBar()
self.TopMenu = wx.Menu()
self.frame_menubar.Append(self.TopMenu, "item")
self.SetMenuBar(self.frame_menubar)
self.SubMenu = wx.Menu()
self.SubMenu.Append(wx.NewId(), 'Sub Item')
# Menu Bar end
self.panel_1 = wx.Panel(self, wx.ID_ANY)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_1.Add((0, 0), 0, 0, 0)
btn_add = wx.Button(self.panel_1, wx.ID_ANY, "Add")
btn_remove = wx.Button(self.panel_1, wx.ID_ANY, "Remove")
self.Bind(wx.EVT_BUTTON, self.on_attach, btn_add)
self.Bind(wx.EVT_BUTTON, self.on_detach, btn_remove)
sizer_1.Add(btn_add)
sizer_1.Add(btn_remove)
self.panel_1.SetSizer(sizer_1)
self.Layout()
# end wxGlade
def on_attach(self, e):
if not self.attached:
self.attached = True
self.TopMenu.AppendSubMenu(self.SubMenu, "Submenu")
def on_detach(self, e):
if self.attached:
self.attached = False
while self.TopMenu.GetMenuItemCount() > 0:
item = self.TopMenu.FindItemByPosition(0)
self.TopMenu.Remove(item)
# end of class MyFrame
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
# end of class MyApp
if __name__ == "__main__":
app = MyApp(0)
app.MainLoop()