Задумывались ли вы, как создать те маленькие значки состояния в системном трее Windows, которые обычно появляются в правом нижнем углу экрана? Инструментарий wxPython предоставляет довольно простой способ сделать это, и эта статья проведет вас через весь процесс.
Работа с кодом
По причинам, которые я не совсем понимаю, wx-компонент, который мы хотим, это wx.TaskBarIcon. Я предполагаю, что это называется, потому что системный трей является частью панели задач, или, возможно, они не различают панель задач и область лотка в других операционных системах. Во всяком случае, сначала вам нужен значок для использования. Вы можете получить свое изображение где угодно. В этом примере мы собираемся использовать изображение «конверта», которое я превратил в код Python с помощью удобной утилиты wxPython img2py. Когда вы запустите изображение через img2py, вы получите что-то вроде этого:
#---------------------------------------------------------------------- # This file was generated by img2py.py # from wx import ImageFromStream, BitmapFromImage from wx import EmptyIcon import cStringIO, zlib def getData(): return zlib.decompress( 'x\xda\x01\x86\x01y\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\ \x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\ \x08d\x88\x00\x00\x01=IDATX\x85\xed\x97[\x9a\x83 \x0c\x85Ol\xf7\x1566#\xec\ \xac,\xace\x1e\xe4b \xfa\xa9\xa3\xe5\xc5<\x15$9\x7fO\xc0\x0b\xd1\xf0@\xcf\ \x18\xba\xaa\xdf\x007\x00\x80g\xfa1\xfe\xfe\x84o\x89ZkA\xc3\x83\x04\x00\x00\ \x8c\xe3x\xa1,\x01\x08p\xce\x89Y\xd1\x82\xfa\xe2y\xc2P\xc5\x1b\x00c\xcc\x05\ \x10Sg\x9ds0\xc6\xac\x030\xf3\x05\x10\x94\xc5\x99y\x1d\xe0\\\x88\xc9z\xe7l\ \x147\xea*\xf5\x18\xfe\x0fB\xf6\xbc\xfcs\xfd\x90-\xde\x07\x8eC\xc8\x9e\x17\ \xdbI]\xbdz#:\x06Q\xf7\xbc8\xb2\x1b`\x1f\xc4R\xcf\x83\xb8\xbe\x1b %\x16\x08\ \x12\xf3Z\xcfu\xe1\xdd\x0eL\x89\xde\xbf\xc0\xcc3\'lU\xb0=\xe7\xcc\x0c\xef\ \xfd\x02\x88\x8c\xa7:\x1b\x13\xbd\xf7\xd1\xca\x90\x0b\'\xb1:\x8a\xf8\xb4>A\ \x94|\xdd\x81E\x80)y~|(\x17\xd6\xa2\x15"0\x87\xe8`\xc9\xdf\x00@\xd9v\x19\xb2\ \xf0|}-<\x1f3\x9bXo\xe3\x1e(\xe2u\xcf\xea\xcd\xb4},\xf7\xc4\n@\xb1\xfd\x98\ \xd0\xdax\t\xa2y\x18\xb5q\x1e\xc8\xa6\x87\xd1\x99\xd6\xeb\xe3\xaaz\xfa0\xe9\ \xf5J\x96\x01\xc2\xe7\xfd5\x00\x00-@\xaf\xe8\xfeZ~\x03t\x07\xf8\x03\x82\xac\ \xa4VT\xfd\xcd\xa3\x00\x00\x00\x00IEND\xaeB`\x82\n\xa7\xa9\xa8' ) def getBitmap(): return BitmapFromImage(getImage()) def getImage(): stream = cStringIO.StringIO(getData()) return ImageFromStream(stream) def getIcon(): icon = EmptyIcon() icon.CopyFromBitmap(getBitmap()) return icon
Все данные изображения находятся в функции getData . Я собираюсь назвать этот файл «email_ico.py». Мы импортируем его в нашу основную программу и вызовем метод getIcon для получения значка, который мы хотим использовать. Давайте посмотрим на основное приложение сейчас:
import wx from mail_ico import getIcon ######################################################################## class MailIcon(wx.TaskBarIcon): TBMENU_RESTORE = wx.NewId() TBMENU_CLOSE = wx.NewId() TBMENU_CHANGE = wx.NewId() TBMENU_REMOVE = wx.NewId() #---------------------------------------------------------------------- def __init__(self, frame): wx.TaskBarIcon.__init__(self) self.frame = frame # Set the image self.tbIcon = getIcon() self.SetIcon(self.tbIcon, "Test") # bind some events self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE) self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.OnTaskBarLeftClick) #---------------------------------------------------------------------- def CreatePopupMenu(self, evt=None): """ This method is called by the base class when it needs to popup the menu for the default EVT_RIGHT_DOWN event. Just create the menu how you want it and return it from this function, the base class takes care of the rest. """ menu = wx.Menu() menu.Append(self.TBMENU_RESTORE, "Open Program") menu.Append(self.TBMENU_CHANGE, "Show all the Items") menu.AppendSeparator() menu.Append(self.TBMENU_CLOSE, "Exit Program") return menu #---------------------------------------------------------------------- def OnTaskBarActivate(self, evt): """""" pass #---------------------------------------------------------------------- def OnTaskBarClose(self, evt): """ Destroy the taskbar icon and frame from the taskbar icon itself """ self.frame.Close() #---------------------------------------------------------------------- def OnTaskBarLeftClick(self, evt): """ Create the right-click menu """ menu = self.tbIcon.CreatePopupMenu() self.PopupMenu(menu) menu.Destroy() ######################################################################## class MyForm(wx.Frame): #---------------------------------------------------------------------- def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial", size=(500,500)) panel = wx.Panel(self) self.tbIcon = MailIcon(self) self.Bind(wx.EVT_CLOSE, self.onClose) #---------------------------------------------------------------------- def onClose(self, evt): """ Destroy the taskbar icon and the frame """ self.tbIcon.RemoveIcon() self.tbIcon.Destroy() self.Destroy() #---------------------------------------------------------------------- # Run the program if __name__ == "__main__": app = wx.App(False) frame = MyForm().Show() app.MainLoop()
Первый класс в основном скопирован прямо из демонстрации wxPython и немного упрощен. Вы можете посмотреть там, если вам нужен более полный пример. В любом случае, мы связываем пару событий в нашем подклассе TaskBarIcon, который позволяет нам закрыть приложение и показать меню соответственно. Вы также заметите, что мы устанавливаем иконку, которую создали в __init__, просто вызывая его метод SetIcon и передавая строку для его всплывающей подсказки.
В методе close мы вызываем фрейм напрямую, чтобы закрыть его. Лучшим способом было бы использовать pubsub здесь. Если вы хотите немного остановиться и прочитать о pubsub, я тоже написал небольшой пост об этом. Остальная часть кода довольно понятна.
Теперь мы можем перейти к подклассу wx.Frame. Здесь мы просто создаем экземпляр класса TaskBarIcon, который мы создали ранее, и привязываем фрейм к EVT_CLOSE . Вы можете спросить об этом. Есть некоторые проблемы с использованием TaskBarIcon в Windows. Если я просто скажу, чтобы рамка закрывалась, она закрывается очень хорошо, но иконка остается, а Python просто висит на земле лалы. Если вы разрешаете пользователю закрываться только с помощью контекстного меню значка на панели задач, тогда вы можете просто добавить туда метод RemoveIcon и self.Destroy (), и вам будет полезно пойти (по какой-то причине RemoveIcon isn ‘ этого достаточно, чтобы избавиться от TaskBarIcon, поэтому вам также нужно сказать, чтобы он тоже сам себя уничтожил) Но если вы позволите пользователю нажимать маленькую «х» в верхнем правом углу, то вам нужно пойматьEVT_CLOSE и разберись с этим соответствующим образом. Когда вы перехватываете это событие, вы НЕ можете просто вызывать self.Close (), иначе вы окажетесь в бесконечном цикле, поэтому мы вместо этого вызываем self.Destroy () .
Завершение
Теперь вы сможете создать собственное приложение TaskBarIcon. Я настоятельно рекомендую посмотреть демонстрацию wxPython, чтобы узнать, что еще вы можете с ней сделать. Я думаю, что добавление значка может добавить немного блеска в ваше приложение, особенно если вам нужно, чтобы оно какое-то время было скрытно, а затем всплыло по команде пользователя.
Дальнейшее чтение
- Создайте мигающий TaskBarIcon
- Еще один блог на эту тему
- TaskBarIcon документация
Источник