1

I’m using Python 3.7 with wxPython 4.0.4. Having a problem with menuBar when I only want a single clickable item. It’s a menu bar with a menu object appended but no menu items are in the menu object. There is no drop-down and no id to bind with. The menuBar object eats the onClick event. I just want to detect when the “Run” item is clicked. Is there any way of catching this event?

1

1 Answer 1

1

Whilst the real answer should be, add a menu item called Run to your Run menu, because that enables the user to choose to run the function, rather than accidently running it by clicking on the menubar, the answer is yes you can.

Bind to the event wx.EVT_MENU_OPEN

import wx
import wx.stc
class MyApp(wx.App):
    def OnInit(self):
        self.frame = MenuFrame(None, title="Menus and MenuBars")
        self.SetTopWindow(self.frame)
        self.frame.Show()

        return True

ID_READ_ONLY = wx.NewId()

class MenuFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MenuFrame, self).__init__(*args, **kwargs)

        # Attributes
        self.panel = wx.Panel(self)
        self.txtctrl = wx.stc.StyledTextCtrl(self.panel,
                                   style=wx.TE_MULTILINE)

        # Layout
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.txtctrl, 1, wx.EXPAND)
        self.panel.SetSizer(sizer)
        self.CreateStatusBar() # For output display

        # Setup the Menu
        menub = wx.MenuBar()

        # File Menu
        filem = wx.Menu()
        filem.Append(wx.ID_NEW, "New")
        filem.Append(wx.ID_OPEN, "Open")
        filem.Append(wx.ID_SAVE, "Save")
        filem.Append(wx.ID_SAVEAS, "Save_As")
        menub.Append(filem, "&File")

        # Edit Menu
        editm = wx.Menu()
        editm.Append(wx.ID_UNDO, "Undo")
        editm.Append(wx.ID_REDO, "Redo")
        editm.Append(wx.ID_COPY, "Copy")
        editm.Append(wx.ID_CUT, "Cut")
        editm.Append(wx.ID_PASTE, "Paste")
        editm.Append(wx.ID_SELECTALL, "SelectAll")
        editm.AppendSeparator()
        editm.Append(ID_READ_ONLY, "Read Only",
                     kind=wx.ITEM_CHECK)
        menub.Append(editm, "Edit")

        # History Menu
        historym = wx.Menu()
        historym.Append(wx.ID_PREVIEW, "Recent")
        menub.Append(historym, "&History")

        # Help Menu
        helpm = wx.Menu()
        helpm.Append(wx.ID_HELP_INDEX, "Hint")
        helpm.Append(wx.ID_ABOUT, "About")
        menub.Append(helpm, "&Help")

        # Run Menu
        runm = wx.Menu()
        menub.Append(runm,"&Run")

        self.SetMenuBar(menub)

        # Event Handlers
        self.Bind(wx.EVT_MENU, self.OnMenu)
        self.Bind(wx.EVT_MENU_OPEN, self.OnMenu)

    def OnMenu(self, event):
        """Handle menu clicks"""
        evt_id = event.GetId()
        if evt_id == 0:
            obj = event.GetMenu()
            if obj.GetTitle() == "&Run":
                self.txtctrl.AddText('Running program\n')
        else:
            self.txtctrl.AddText("Menu item "+str(evt_id)+" selected\n")

if __name__ == "__main__":
    app = MyApp()
    app.MainLoop()

You have a choice of:

  1. EVT_MENU_OPEN: A menu is about to be opened. On Windows, this is only sent once for each navigation of the menubar (up until all menus have closed).
  2. EVT_MENU_CLOSE: A menu has been just closed. Notice that this event is currently being sent before the menu selection ( wxEVT_MENU ) event, if any.
  3. EVT_MENU_HIGHLIGHT: The menu item with the specified id has been highlighted: used to show help prompts in the status bar by wx.Frame
  4. EVT_MENU_HIGHLIGHT_ALL: A menu item has been highlighted, i.e. the currently selected menu item has changed.

That said, I still think that you should add a Run menu item to the Run menu enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

This works but I haven't found a way to prevent the empty submenu from opening or close it when clicked, and an attempted hack to remove or replace the menu in the event crashes the program.
@dw1 The issue is really that you want a Cat to bark or a menu to act, just for a single entry, as a toolbar. Perhaps adding a title to the menu will make it look a little better, rather than having it blank. i.e. runm = wx.Menu("Run Instantly")

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.