Контекстное меню и панель инструментов

Продолжим тему меню и рассмотрим создание контекстного меню. Часто оно появляется при правом щелчке мыши в области приложения. Давайте в качестве примера сделаем вот такой простой функционал:

Во-первых, нам здесь понадобится реакция на нажатие правой кнопки мыши в области окна. За это отвечает событие:

EVT_RIGHT_DOWN

Подключить его можно так:

self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)

И далее сам обработчик:

    def OnRightDown(self, event):

В нем мы создадим и отобразим контекстное меню. Вначале оно создается как обычное меню:

ctx = wx.Menu()
it_min = ctx.Append(wx.ID_ANY, "Минимизировать")
it_max = ctx.Append(wx.ID_ANY, "Распахнуть")
self.Bind(wx.EVT_MENU, self.onMinimize, it_min)
self.Bind(wx.EVT_MENU, self.onMaximize, it_max)

Здесь прописаны два обработчика:

    def onMinimize(self, event):
        self.Iconize()
 
    def onMaximize(self, event):
        self.Maximize()

Метод Iconize() схлопывает окно, а Maximize() – распахивает. Затем, меню отображается с помощью метода:

    def OnRightDown(self, event):
        self.PopupMenu(ctx, event.GetPosition())

Обратите внимание, мы берем текущую позицию курсора с помощью метода GetPosition через класс MouseEvent, на который ссылается параметр event. В будущем вам понадобятся и другие возможности классов Event и все они (методы и свойства) приведены в официальной документации. Например, по этой ссылке

https://docs.wxpython.org/wx.Event.html

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

Запускаем программу и видим, что все работает как и задумано. Но в этой программе есть один недостаток: мы при правом щелчке мыши каждый раз заново создаем меню. Это не самый рациональный путь: его лучше создать один раз, а затем многократно использовать. И, кроме того, само меню удобнее организовать в виде отдельного класса, производного от базового Menu:

class AppContextMenu(wx.Menu):
    def __init__(self, parent):
        self.parent = parent
        super().__init__()
 
        it_min = self.Append(wx.ID_ANY, "Минимизировать")
        it_max = self.Append(wx.ID_ANY, "Распахнуть")
        self.Bind(wx.EVT_MENU, self.onMinimize, it_min)
        self.Bind(wx.EVT_MENU, self.onMaximize, it_max)
 
    def onMinimize(self, event):
        self.parent.Iconize()
 
    def onMaximize(self, event):
        self.parent.Maximize()

Благодаря этому отдельному классу у нас получается модульность в программе: весь функционал контекстного меню вынесен в отдельный класс. Далее, в конструкторе главного окна приложения мы его создаем:

self.ctx = AppContextMenu(self)

И при правом щелчке мыши, вызываем:

self.PopupMenu(self.ctx, event.GetPosition())

Все, теперь наше меню создается единожды и вызывается по мере необходимости.

Панель инструментов

Панель инструментов (toolbar) представляет собой набор элементов управления, которые наиболее часто используются при работе с этим приложением.

Для создания панели toolbar достаточно вызвать метод:

toolbar = self.CreateToolBar()

И по умолчанию получим горизонтальное расположение под нашим меню:

Для добавления элемента управления используется метод:

br_quit = toolbar.AddTool(wx.ID_ANY, "Выход", wx.Bitmap("exit32.png"))

И при работе под ОС Windows обязательно нужно вызвать метод:

toolbar.Realize()

для отображения кнопки на toolbar’e. Под ОС Linux это необязательное действие, но так как программы обычно пишутся как кросс-платформенные, то лучше всегда записывать эту строчку.

Теперь, при запуске программы мы увидим следующее:

Далее, нам нужно связать нажатие на эту кнопку с определенным действием. Естественно, это делается с помощью все того же метода Bind:

self.Bind(wx.EVT_TOOL, self.onQuit, br_quit)

Помимо обычных кнопок в виде иконок на тулбар можно добавлять следующие элементы:

toolbar.AddSeparator()
br_undo = toolbar.AddTool(wx.ID_UNDO, "", wx.Bitmap("undo32.png"))
br_redo = toolbar.AddTool(wx.ID_REDO, "", wx.Bitmap("redo32.png"))
toolbar.AddSeparator()
toolbar.AddCheckTool(wx.ID_ANY, "", wx.Bitmap("sound32.png"))
toolbar.AddRadioTool(wx.ID_ANY, "", wx.Bitmap("sound_on32.png"))
toolbar.AddRadioTool(wx.ID_ANY, "", wx.Bitmap("sound_off32.png"))

Здесь AddCheckTool() создает кнопку типа нажать/отжать, а метод AddRadioTool() набор кнопок-переключателей. Все это выглядит следующим образом:

Также отдельные элементы можно делать активными и неактивными:

toolbar.EnableTool(wx.ID_REDO, False)

Теперь кнопка Redo будет недоступна для использования. Соответственно, вернуть активность можно, указав значение True вторым параметром:

toolbar.EnableTool(wx.ID_REDO, True)

Наконец, саму панель инструментов можно располагать в окне разными способами:

toolbar = self.CreateToolBar(wx.TB_RIGHT)
toolbar = self.CreateToolBar(wx.TB_LEFT)
toolbar = self.CreateToolBar(wx.TB_BOTTOM)

Опять же полный функционал (возможности) использования тулбаров смотрите в документации

https://docs.wxpython.org

В частности по панелям инструментов:

https://docs.wxpython.org/wx.ToolBar.html

Рассказать обо всем в видеоуроках просто нереально. Да это и ни к чему. Возможности пакета wxPython постоянно меняются от версии к версии: добавляются новые возможности, виджеты, а некоторые устаревшие подходы отмирают. Поэтому при работе с любым сторонним модулем нужно уметь пользоваться его документацией.

Видео по теме