如何在 wxPython 中获取选定的菜单项?

How to get selected menu item in wxPython?

在我的程序中,我有一个包含插入子菜单的上下文菜单。我不想为子菜单中的每个选项创建不同的功能,而是想将所有选项绑定到同一个功能。有没有办法确定所选项目的标签或 ID,以便我可以将其传递给不同的函数?

编辑:经过一些研究,我找到了函数 GetId(),这是我想要的,但我仍然需要从 id 中获取标签。我也许可以使用 FindWindowById,它是 wx.Window 的函数,但它只能查看 window 的子项。该框架似乎不是子菜单中项目的父级,所以我不能只做 frame.FindWindowById(id)

使用 partial 将选项(一些唯一 ID)发送到常用函数。如果您有很多菜单项,请使用 for() 循环,将 return 存储在列表中(而不是 menu_item_x),并递增计数器以发送到函数。

import wx
from functools import partial

class MenuCallback(object):

    def __init__(self, parent, id):
        self.frame=wx.Frame(None)
        menu_bar = wx.MenuBar()
        menu1 = wx.Menu()
        menu_item_1 = menu1.Append(-1, "&Option #1")
        menu_item_2 = menu1.Append(-1, "&Option #2")
        menu_item_3 = menu1.Append(-1, "&Exit...")

        menu_bar.Append(menu1, "&File")
        self.frame.SetMenuBar(menu_bar)
        self.frame.Bind(wx.EVT_MENU, partial(self.option_chosen, 1),
                        menu_item_1)
        self.frame.Bind(wx.EVT_MENU, partial(self.option_chosen, 2),
                        menu_item_2)
        self.frame.Bind(wx.EVT_MENU, self.on_close, menu_item_3)

        self.frame.Show(True)

    def option_chosen(self, number, event):
        print "option chosen =", number

    def on_close(self, event):
        self.frame.Close(True)

app = wx.PySimpleApp()
MC=MenuCallback(parent=None, id=-1)
app.MainLoop()

它可能不漂亮,但我发现使用带有菜单 ID 范围的列表很有效。不仅容易理解而且灵活,像这样:

import wx

class MenuCallback(wx.Frame):

    def __init__(self, *args, **kwds):
        self.frame=wx.Frame.__init__(self, *args, **kwds)
        self.menubar = wx.MenuBar()
        menu1 = wx.Menu()
        menu_item_1 = menu1.Append(wx.ID_OPEN, "&File")
        menu_item_2 = menu1.Append(wx.ID_EXIT, "&Exit...")
    #Build a list of things via another function or just a declaration
        self.list_of_things = ["Thing No 1", "Thing No 2", "Thing No 3"]
        list_used = wx.Menu()
        thing_count = 101

        for thing in self.list_of_things:
            t1 = wx.MenuItem(list_used, thing_count, thing)
            list_used.AppendItem(t1)
            thing_count +=1

        thing_end = wx.MenuItem(list_used,199,'End of List')
        list_used.AppendItem(thing_end)

        menu1.AppendMenu(wx.ID_FILE,'&Things',list_used)
        self.menubar.Append(menu1, "&File")
        self.SetMenuBar(self.menubar)
    # Create bindings for the Thing list
        i_count = 101
        for i in self.list_of_things:
            self.Bind(wx.EVT_MENU, self.OnThingOpen, id=i_count)
            i_count = i_count + 1
        self.Bind(wx.EVT_MENU, self.OnThingEnd, id=199)
        self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
        self.Show(True)

    def OnThingOpen(self, event):
        id_index = 101
        id_selected = event.GetId()
        id_selected = id_selected - id_index
        print "Option =", id_selected
        print "Thing selected =", str(self.list_of_things[id_selected])

    def OnThingEnd(self, event):
        id_selected = event.GetId()
        print "Option =", id_selected

    def OnClose(self, event):
        self.Close()

    if __name__ == '__main__':
        app = wx.App()
        MC=MenuCallback(parent=None, id=-1)
        app.MainLoop()

在为您的问题提供了解决方案后,我意识到应该有另一种方法来实现我的解决方案。事实上有,我可能会自己采用它,因为它更干净并且使用更少的内存。这使用 event.GetEventObject() 方法。

import wx

class MenuCallback(wx.Frame):

    def __init__(self, *args, **kwds):
        self.frame=wx.Frame.__init__(self, *args, **kwds)
        self.menubar = wx.MenuBar()
#        self.statusbar = wx.StatusBar(self-1)
        self.CreateStatusBar()
        self.SetStatusText("Demonstration of wxPython")
        menu1 = wx.Menu()
        menu_item_1 = menu1.Append(wx.ID_OPEN, "&File")
        menu_item_2 = menu1.Append(wx.ID_EXIT, "&Exit...")
    #Build a list of things via another function or just a declaration
        self.list_of_things = ["Thing No 1", "Thing No 2", "Thing No 3"]
        list_used = wx.Menu()
        thing_count = 101

        for thing in self.list_of_things:
            t1 = wx.MenuItem(list_used, thing_count, thing)
            list_used.AppendItem(t1)
            thing_count +=1

        thing_end = wx.MenuItem(list_used,199,'End of List')
        list_used.AppendItem(thing_end)

        menu1.AppendMenu(wx.ID_FILE,'&Things',list_used)
        menu1.SetHelpString(wx.ID_FILE, 'Select from the list of things')

        self.menubar.Append(menu1, "&File")
        self.SetMenuBar(self.menubar)
    # Create bindings for the Thing list
        i_count = 101
        for i in self.list_of_things:
            self.Bind(wx.EVT_MENU, self.OnThingOpen, id=i_count)
            i_count = i_count + 1
        self.Bind(wx.EVT_MENU, self.OnThingEnd, id=199)
        self.Bind(wx.EVT_MENU, self.OnClose, id=wx.ID_EXIT)
        self.Show(True)

    def OnThingOpen(self, event):
        id_selected = event.GetId()
        obj = event.GetEventObject()
        print "Option =", id_selected
        print obj.GetLabel(id_selected)
        print "From the range:"
        for i in range(obj.MenuItemCount):
            print "\t\t", obj.MenuItems[i].GetLabel()

    def OnThingEnd(self, event):
        pass

    def OnClose(self, event):
        self.Close()

if __name__ == '__main__':
    app = wx.App()
    MC=MenuCallback(parent=None, id=-1)
    app.MainLoop()