Статьи

Создание меню с помощью wxPython

Меню вездесущи. Они есть почти во всех настольных программах. Вы используете их для редактирования настроек или настройки вашей программы. В wxPython есть несколько вариантов меню на выбор. Наиболее знакомым, вероятно, является wx.Menu. Но есть всплывающие меню и чистая реализация Python, известная как FlatMenu. Мы просто расскажем о wx.Menu и всплывающих меню, потому что они связаны друг с другом. FlatMenu также включает в себя API панели инструментов, так что вам придется подождать еще одну статью, которая сама будет охватывать этот виджет. Давайте начнем эту вечеринку меню!

 

Простой пример меню

Мы начнем с чего-то действительно простого: меню только с элементом меню выхода. Вот код:

 

import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="wx.Menu Tutorial")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        exitMenuItem = fileMenu.Append(wx.NewId(), "Exit",
                                       "Exit the application")
        menuBar.Append(fileMenu, "&File")
        self.Bind(wx.EVT_MENU, self.onExit, exitMenuItem)
        self.SetMenuBar(menuBar)
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """"""
        self.Close()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Давайте разберемся с этим немного. Чтобы создать строку меню, мы создаем экземпляр wx.MenuBar. Затем мы создаем экземпляр wx.Menu, который мы называем filemenu., Наконец, чтобы добавить элемент «Выход», мы добавляем к нему некоторые данные. По сути, мы добавляем wx.MenuItem, но это своего рода ярлык, поскольку сначала мы не создавали экземпляр wx.MenuItem. Мы покажем, как это сделать, в нашем следующем примере. Обратите внимание, что когда мы добавляем элемент, мы должны передать идентификатор, строку метки и строку состояния. Последний из них будет отображаться в строке состояния, когда вы наводите курсор мыши на элемент меню, если у вас есть строка состояния. Обратите внимание, что для присоединения обработчика событий к пункту меню вам нужно использовать событие EVT_MENU и привязать его к фрейму. Затем мы добавляем само меню к объекту MenuBar и также передаем ему строку, которая в данном случае называется «Файл». Наконец, мы вызываем метод SetMenuBar фрейма, чтобы прикрепить строку меню к фрейму.

 

Добавление картинки в меню

 

Это все, что нужно для создания меню! Теперь давайте посмотрим на более сложный пример! Примечание. Чтобы следовать приведенному ниже примеру, вам необходимо использовать собственный файл изображения.

 

import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="wx.Menu Tutorial")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        # create the menubar
        menuBar = wx.MenuBar()
 
        # create the first menu (starting on left)
        carMenu = wx.Menu()
        carMenu.Append(101, "&Ford", "An American Automaker")
        carMenu.Append(102, "&Nissan", "")
        carMenu.Append(103, "&Toyota", "Buy Japanese!")
        carMenu.Append(104, "&Close", "Close the application")
 
        # add a picture to a menu
        picMenu = wx.Menu()
        item = wx.MenuItem(picMenu, wx.ID_ANY, "Snake", "This menu has a picture!")
        img = wx.Image('snake32.bmp', wx.BITMAP_TYPE_ANY)
        item.SetBitmap(wx.BitmapFromImage(img))
        picMenu.AppendItem(item)
 
        # add menus to menubar
        menuBar.Append(carMenu, "&Vehicles")
        menuBar.Append(picMenu, "&Picture")
        self.SetMenuBar(menuBar)
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """"""
        self.Close()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Этот пример похож на первый. Основное отличие состоит в том, что мы добавляем несколько элементов в меню « Файл», и у нас есть два меню. Обратите внимание, что на этот раз мы фактически указываем наши идентификационные номера явно. Обычно это не рекомендуется, поскольку вы можете случайно скрыть один из обязательных идентификаторов wx. Тем не менее, вы время от времени видите примеры этого в Интернете, поэтому вам следует знать об этой практике. Следующая большая разница не наступит, пока мы не доберемся до picMenu . Здесь мы на самом деле создать wx.MenuItem и добавить фотографию к нему через wx.Image и в MENUITEM по SetBitmap методу. В остальном все почти так же.

Теперь мы потратим некоторое время, чтобы посмотреть, как добавить радио и проверить кнопки в нашем меню.

Добавление радио или кнопки проверки

 

Добавить радио или кнопку проверки в ваше меню на самом деле довольно легко. Давайте на минутку посмотрим, как это делается!

 

# radiocheck.py
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="wx.Menu Tutorial")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        # Create menu bar
        menuBar = wx.MenuBar()
 
        # Create radio menu
        radioMenu = wx.Menu()
        idleItem = radioMenu.Append(wx.NewId(), "IDLE",
                                   "a Python shell using tcl/tk as GUI",
                                   wx.ITEM_RADIO)
        pyCrustItem = radioMenu.Append(wx.NewId(),"PyCrust",
                                      "a Python shell using wxPython as GUI",
                                      wx.ITEM_RADIO)
        psiItem = radioMenu.Append(wx.NewId(), "psi",
                                  "a simple Python shell using wxPython as GUI",
                                  wx.ITEM_RADIO)
        menuBar.Append(radioMenu, "&Radio")
 
        # create check menu
        checkMenu = wx.Menu()
        wgItem = checkMenu.Append(wx.NewId(), "Wells Fargo", "", wx.ITEM_CHECK)
        citiItem = checkMenu.Append(wx.NewId(), "Citibank", "", wx.ITEM_CHECK)
        geItem = checkMenu.Append(wx.NewId(), "GE Money Bank", "", wx.ITEM_CHECK)
        menuBar.Append(checkMenu, "&Check")
 
        # Attach menu bar to frame
        self.SetMenuBar(menuBar)
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

Да, как видите, все, что вам нужно сделать, это добавить флаг wx.ITEM_RADIO или wx.ITEM_CHECK в качестве параметра типа kind , который является 4-м параметром. Почему он называется «добрый», а не «стиль», как другие виджеты? Что ж, обсуждая это на IRC-канале wxPython, Робин Данн (создатель wxPython) отметил, что это может быть из-за того, что это разные виды пунктов меню.

Суб-меню

 

Библиотека wxPython также поддерживает подменю. Вот действительно простой пример, чтобы показать вам, как это делается.

# submenu.py
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="wx.Menu Tutorial")
 
        self.panel = wx.Panel(self, wx.ID_ANY)
 
        menuBar = wx.MenuBar()
        fileMenu = wx.Menu()
        openMenuItem = fileMenu.Append(wx.NewId(), "Open")
 
        # create a submenu
        subMenu = wx.Menu()
        historyMenuItem = subMenu.Append(wx.NewId(), "Show History")
        fileMenu.AppendMenu(wx.NewId(), "History", subMenu)
 
        exitMenuItem = fileMenu.Append(wx.NewId(), "Exit",
                                       "Exit the application")
        menuBar.Append(fileMenu, "&File")
        self.Bind(wx.EVT_MENU, self.onExit, exitMenuItem)
        self.SetMenuBar(menuBar)
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """"""
        self.Close()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

 

Ключевым моментом здесь является то, что вместо использования метода Append для файлового меню, мы вместо этого используем его метод AppendMenu. Как следует из названия, он позволяет программисту фактически добавлять меню вместо пункта меню. Да это все!

Всплывающие меню (AKA: ContextMenus)

 

Всплывающие меню — это то, что вы видите, когда щелкаете правой кнопкой мыши ссылку в браузере или в файле. Они также известны как контекстные меню. Вот довольно простой пример для изучения:

# submenu.py
import wx
 
########################################################################
class MyForm(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Popup Menu Tutorial")
 
        panel = wx.Panel(self, wx.ID_ANY)
 
        lbl = wx.StaticText(panel, label="Right click anywhere!")
        self.Bind(wx.EVT_CONTEXT_MENU, self.onContext)
 
    #----------------------------------------------------------------------
    def onContext(self, event):
        """
        Create and show a Context Menu
        """
 
        # only do this part the first time so the events are only bound once 
        if not hasattr(self, "popupID1"):
            self.popupID1 = wx.NewId()
            self.itemTwoId = wx.NewId()
            self.itemThreeId = wx.NewId()
            self.Bind(wx.EVT_MENU, self.onPopup, id=self.popupID1)
            self.Bind(wx.EVT_MENU, self.onPopup, id=self.itemTwoId)
            self.Bind(wx.EVT_MENU, self.onExit, id=self.itemThreeId)
 
        # build the menu
        menu = wx.Menu()
        itemOne = menu.Append(self.popupID1, "ItemOne")
        itemTwo = menu.Append(self.itemTwoId, "ItemTwo")
        itemThree = menu.Append(self.itemThreeId, "Exit")
 
        # show the popup menu
        self.PopupMenu(menu)
        menu.Destroy()
 
    #----------------------------------------------------------------------
    def onExit(self, event):
        """
        Exit program
        """
        self.Close()
 
    #----------------------------------------------------------------------
    def onPopup(self, event):
        """
        Print the label of the menu item selected
        """
        itemId = event.GetId()
        menu = event.GetEventObject()
        menuItem = menu.FindItemById(itemId)
        print menuItem.GetLabel()
 
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

 

Для начала мы привязываем wx.EVT_CONTEXT_MENU к фрейму. Это позволяет нам щелкнуть правой кнопкой мыши в любом месте и запустить событие контекстного меню, которое создаст и покажет наше всплывающее меню. Код в методе onContext свободно основан на демонстрации wxPython для всплывающего меню. Как видите, мы используем условный оператор, чтобы проверить, связали ли мы уже события меню. Если у нас есть, мы не связываем их снова. Затем мы создаем наше меню так же, как и раньше. Наконец, мы вызываем метод PopupMenu фрейма и передаем его нашему новому меню. Это покажет меню пользователю. Когда пользователь нажимает на элемент меню, он запускает событие, и меню будет уничтожено.

Первые два пункта меню связаны с нашим методом onPopup . Это позволяет нам увидеть, как мы можем получить доступ к меню и атрибутам MenuItem. Вы можете получить идентификатор меню с событием и само меню с помощью метода GetEventObject события. Затем вы можете использовать метод FindItemById меню, чтобы получить дескриптор самого элемента меню. Наконец мы распечатываем метку пункта меню.

Завершение

Теперь вы должны знать большинство методов меню и как их создавать, связывать события и создавать различные виды пунктов меню. Вы даже знаете, как создавать всплывающие меню! Теперь вы можете сделать так, чтобы у ваших приложений были необычные меню.

 

Дальнейшее чтение

Источник