1

My goal: the user clicks a button. From the button pops up a two-level menu. The user clicks on something, and this triggers a callback which does stuff.

Here is a minimal example:

import wx

class MyApp(wx.App):
    def OnInit(self):
        frame = TestFrame(None, -1, "Hello from wxPython")
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

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

        sizer = wx.BoxSizer()
        button = wx.Button(self, label='Click me')
        sizer.Add(button)
        self.SetSizerAndFit(sizer)

        mainmenu = wx.Menu()
        next_id = 1000000
        submenus = {}

        for title in ['Submenu 1', 'Submenu 2', 'Submenu 3']:
            mit = wx.MenuItem(mainmenu, id=next_id, text=title)
            submenu = wx.Menu()
            mit.SetSubMenu(submenu)
            mainmenu.AppendItem(mit)

            next_id = next_id + 1
            submenus[title] = submenu

        items = [('Submenu 1', 'foo'),
                 ('Submenu 1', 'bar'),
                 ('Submenu 2', 'one'),
                 ('Submenu 2', 'two'),
                 ('Submenu 2', 'three'),
                 ('Submenu 3', 'zif'),
                 ('Submenu 3', 'zaf')]

        for title, item in items:
            submenu = submenus[title]
            mit = wx.MenuItem(submenu, id=next_id, text=item)
            submenu.AppendItem(mit)
            next_id = next_id + 1

            def callback(e, title=title, item=item):
                print 'Item clicked: %s, %s' % (title, item)

            self.Bind(wx.EVT_MENU, callback, mit)


        def show(e):
            self.PopupMenu(mainmenu, button.GetPosition())
        button.Bind(wx.EVT_BUTTON, show)

app = MyApp(0)
app.MainLoop()

Also:

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wx
>>> wx.version()
'2.8.10.1 (msw-unicode)'

1 Answer 1

2

You are handling ID generation yourself and in doing that mixing up IDs, anyway you do not need to generate IDs yourself use wx.NewId(), if you replace next_id with that it will work e.g.

mit = wx.MenuItem(submenu, id=wx.NewId(), text=item)
Sign up to request clarification or add additional context in comments.

2 Comments

As easy as that. Huh. I don't like handling my own ID generation, but I concluded that I needed to for menu items (I don't remember why..). Everywhere else I omit the id= parameter. I didn't know about wx.NextId().
Ah, I remember. It's because a MenuItem with an id of -1 is a separator.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.