Delete a menu's submenu?

I’m trying to delete and recreate a submenu.

However, the Remove() method doesn’t take a wxMenuItem, so the submenu can’t be removed.

What’s wrong here? This line fails:
self.file_menu.Remove(self.sub_menu)

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kw):
        super(MyFrame, self).__init__(*args, **kw)

        # Create a menu bar
        self.menu_bar = wx.MenuBar()

        # Create a main menu
        self.file_menu = wx.Menu()

        # Create a submenu
        self.sub_menu = wx.Menu()
        self.add_sub_menu_items()

        # Add the submenu to the main menu
        self.file_menu.AppendSubMenu(self.sub_menu, "Submenu")

        # Add the main menu to the menu bar
        self.menu_bar.Append(self.file_menu, "&File")

        # Set the menu bar for the frame
        self.SetMenuBar(self.menu_bar)

        # Create a button to destroy and recreate the submenu
        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel, label="Recreate Submenu")

        self.button.Bind(wx.EVT_BUTTON, self.on_button_click)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.button, 0, wx.ALL | wx.CENTER, 5)
        self.panel.SetSizer(sizer)

    def add_sub_menu_items(self):
        self.sub_menu.Append(wx.ID_ANY, "Item 1")
        self.sub_menu.Append(wx.ID_ANY, "Item 2")
        self.sub_menu.Append(wx.ID_ANY, "Item 3")

    def on_button_click(self, event):
        # Remove the existing submenu
        self.file_menu.Remove(self.sub_menu)

        # Create a new submenu
        self.sub_menu = wx.Menu()
        self.add_sub_menu_items()

        # Add the new submenu to the main menu
        self.file_menu.AppendSubMenu(self.sub_menu, "Submenu")

        # Refresh the menu bar to apply changes
        self.menu_bar.Refresh()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame(None, title="Recreate Submenu Example")
    frame.Show(True)
    app.MainLoop()

This appears to work using wxPython 4.2.2 gtk3 (phoenix) wxWidgets 3.2.6 + Python 3.12.3 + Linux Mint 22.1

    def on_button_click(self, event):
        # Remove the existing submenu
        id = self.file_menu.FindItem("Submenu")
        self.file_menu.Remove(id)

        # Create a new submenu
        self.sub_menu = wx.Menu()
        self.add_sub_menu_items()

        # Add the new submenu to the main menu
        self.file_menu.AppendSubMenu(self.sub_menu, "New Submenu")

        # Refresh the menu bar to apply changes
        self.menu_bar.Refresh()

However, the docs say that Remove() doesn’t delete the associated C++ object, so I’m not sure if it will cause a memory leak.

Below is an alternative example that keeps a reference to the Menu Item associated with the Sub Menu. I added a numeric suffix just to demonstrate that it is actually creating a new Sub Menu each time you click the button.

import wx

class MyFrame(wx.Frame):
    def __init__(self, *args, **kw):
        super(MyFrame, self).__init__(*args, **kw)

        # Create a menu bar
        self.menu_bar = wx.MenuBar()

        # Create a main menu
        self.file_menu = wx.Menu()

        # Create a submenu
        self.sub_menu = wx.Menu()
        self.add_sub_menu_items()

        self.count = 1

        # Add the submenu to the main menu
        self.sub_menu_item = self.file_menu.AppendSubMenu(self.sub_menu, f"Submenu {self.count}")

        # Add the main menu to the menu bar
        self.menu_bar.Append(self.file_menu, "&File")

        # Set the menu bar for the frame
        self.SetMenuBar(self.menu_bar)

        # Create a button to destroy and recreate the submenu
        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel, label="Recreate Submenu")

        self.button.Bind(wx.EVT_BUTTON, self.on_button_click)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.button, 0, wx.ALL | wx.CENTER, 5)
        self.panel.SetSizer(sizer)

    def add_sub_menu_items(self):
        self.sub_menu.Append(wx.ID_ANY, "Item 1")
        self.sub_menu.Append(wx.ID_ANY, "Item 2")
        self.sub_menu.Append(wx.ID_ANY, "Item 3")

    def on_button_click(self, event):
        # Remove the existing submenu
        item = self.file_menu.Remove(self.sub_menu_item)

        # Create a new submenu
        self.sub_menu = wx.Menu()
        self.add_sub_menu_items()

        # Add the new submenu to the main menu
        self.count += 1
        self.sub_menu_item = self.file_menu.AppendSubMenu(self.sub_menu, f"Submenu {self.count}")

        # Refresh the menu bar to apply changes
        self.menu_bar.Refresh()

if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame(None, title="Recreate Submenu Example")
    frame.Show(True)
    app.MainLoop()

well, you’ll have to use the MenuItem


        # Add the submenu to the main menu
        self.smi = self.file_menu.AppendSubMenu(self.sub_menu, "Submenu")

like this

        # Remove the existing submenu
        self.file_menu.Remove(self.smi)

:wink: