Rápido y fácil: ¿trayicon con python?

Solo necesito un ejemplo rápido de cómo colocar fácilmente un icono con python en mi bandeja del sistema. Esto significa: ejecuto el progtwig, no aparece ninguna ventana, solo aparece un icono de la bandeja (tengo un archivo png) en la bandeja del sistema y cuando hago clic con el botón derecho en él aparece un menú con algunas opciones (y cuando hago clic en en una opción, se ejecuta una función). ¿Es eso posible? No necesito ninguna ventana en absoluto …

Ejemplos / fragmentos de código son muy apreciados! :RE

Para Windows y Gnome

¡Aqui tienes! wxPython es la bomba. Adaptado de la fuente de mi aplicación Feed Notifier .

import wx TRAY_TOOLTIP = 'System Tray Demo' TRAY_ICON = 'icon.png' def create_menu_item(menu, label, func): item = wx.MenuItem(menu, -1, label) menu.Bind(wx.EVT_MENU, func, id=item.GetId()) menu.AppendItem(item) return item class TaskBarIcon(wx.TaskBarIcon): def __init__(self): super(TaskBarIcon, self).__init__() self.set_icon(TRAY_ICON) self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_left_down) def CreatePopupMenu(self): menu = wx.Menu() create_menu_item(menu, 'Say Hello', self.on_hello) menu.AppendSeparator() create_menu_item(menu, 'Exit', self.on_exit) return menu def set_icon(self, path): icon = wx.IconFromBitmap(wx.Bitmap(path)) self.SetIcon(icon, TRAY_TOOLTIP) def on_left_down(self, event): print 'Tray icon was left-clicked.' def on_hello(self, event): print 'Hello, world!' def on_exit(self, event): wx.CallAfter(self.Destroy) def main(): app = wx.PySimpleApp() TaskBarIcon() app.MainLoop() if __name__ == '__main__': main() 

wx.PySimpleApp en desuso, aquí le indicamos cómo usar wx.App en su lugar

Me tomó un tiempo para resolver esto, así que pensé que iba a compartir. wx.PySimpleApp está en desuso en wxPython 2.9 y posteriores. Aquí está el script original de FogleBird usando wx.App en su lugar.

 import wx TRAY_TOOLTIP = 'System Tray Demo' TRAY_ICON = 'icon.png' def create_menu_item(menu, label, func): item = wx.MenuItem(menu, -1, label) menu.Bind(wx.EVT_MENU, func, id=item.GetId()) menu.AppendItem(item) return item class TaskBarIcon(wx.TaskBarIcon): def __init__(self, frame): self.frame = frame super(TaskBarIcon, self).__init__() self.set_icon(TRAY_ICON) self.Bind(wx.EVT_TASKBAR_LEFT_DOWN, self.on_left_down) def CreatePopupMenu(self): menu = wx.Menu() create_menu_item(menu, 'Say Hello', self.on_hello) menu.AppendSeparator() create_menu_item(menu, 'Exit', self.on_exit) return menu def set_icon(self, path): icon = wx.IconFromBitmap(wx.Bitmap(path)) self.SetIcon(icon, TRAY_TOOLTIP) def on_left_down(self, event): print 'Tray icon was left-clicked.' def on_hello(self, event): print 'Hello, world!' def on_exit(self, event): wx.CallAfter(self.Destroy) self.frame.Close() class App(wx.App): def OnInit(self): frame=wx.Frame(None) self.SetTopWindow(frame) TaskBarIcon(frame) return True def main(): app = App(False) app.MainLoop() if __name__ == '__main__': main() 

Si puede garantizar Windows y no desea introducir las dependencias pesadas de wx, puede hacerlo con las extensiones pywin32 .

También vea esta pregunta .

Para Ubuntu

 class TrayIcon: def init(): iconPath = {"Windows":os.path.expandvars("%PROGRAMFILES%/MyProgram/icon.png"), "Linux":"/usr/share/icons/myprogramicon.png"} if platform.system()=="Linux": import gtk import appindicator # Ubuntu apt-get install python-appindicator # Create an application indicator try: gtk.gdk.threads_init() gtk.threads_enter() icon = iconPath[platform.system()] indicator = appindicator.Indicator("example-simple-client", "indicator-messages", appindicator.CATEGORY_APPLICATION_STATUS) indicator.set_icon(icon) indicator.set_status (appindicator.STATUS_ACTIVE) indicator.set_attention_icon ("indicator-messages-new") menu = gtk.Menu() menuTitle = "Quit" menu_items = gtk.MenuItem(menuTitle) menu.append(menu_items) menu_items.connect("activate", TrayIcon.QuitApp, menuTitle) menu_items.show() menuTitle = "About My Program" menu_items = gtk.MenuItem(menuTitle) menu.append(menu_items) menu_items.connect("activate", TrayIcon.AboutApp, menuTitle) menu_items.show() indicator.set_menu(menu) except: pass # Run the app indicator on the main thread. try: t = threading.Thread(target=gtk.main) t.daemon = True # this means it'll die when the program dies. t.start() #gtk.main() except: pass finally: gtk.threads_leave() @staticmethod def AboutApp(a1,a2): gtk.threads_enter() dialog = gtk.Dialog("About", None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) label = gtk.Label("My Program v0.0.1, (C)opyright ME 2015. All rights reserved.") dialog.vbox.pack_start(label) label.show() label2 = gtk.Label("example.com\n\nFor more support contact me@gmail.com") label2.show() dialog.action_area.pack_end(label2) response = dialog.run() dialog.destroy() gtk.threads_leave() @staticmethod def QuitApp(a1, a2): sys.exit(0) 

Multiplataforma

Ver PyQt: Mostrar menú en una aplicación de la bandeja del sistema.

Versión 2018

 import wx.adv import wx TRAY_TOOLTIP = 'Name' TRAY_ICON = 'icon.png' def create_menu_item(menu, label, func): item = wx.MenuItem(menu, -1, label) menu.Bind(wx.EVT_MENU, func, id=item.GetId()) menu.Append(item) return item class TaskBarIcon(wx.adv.TaskBarIcon): def __init__(self, frame): self.frame = frame super(TaskBarIcon, self).__init__() self.set_icon(TRAY_ICON) self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.on_left_down) def CreatePopupMenu(self): menu = wx.Menu() create_menu_item(menu, 'Site', self.on_hello) menu.AppendSeparator() create_menu_item(menu, 'Exit', self.on_exit) return menu def set_icon(self, path): icon = wx.Icon(path) self.SetIcon(icon, TRAY_TOOLTIP) def on_left_down(self, event): print ('Tray icon was left-clicked.') def on_hello(self, event): print ('Hello, world!') def on_exit(self, event): wx.CallAfter(self.Destroy) self.frame.Close() class App(wx.App): def OnInit(self): frame=wx.Frame(None) self.SetTopWindow(frame) TaskBarIcon(frame) return True def main(): app = App(False) app.MainLoop() if __name__ == '__main__': main() 

Una alternativa si está intentando ejecutar un progtwig basado en Python en segundo plano, puede ejecutarlo como un servicio. Echa un vistazo a esta receta de estado activo es bastante útil. Creo que una de las opciones es convertir su aplicación a exe con py2exe o pyinstall.

http://code.activestate.com/recipes/551780/

Para un ejemplo, refiérase a este hilo -> pregunta wx.

wxPython "classic" -> [new API] wxPython 'Phoenix' (Py3)

Sí. Hay un ejemplo multiplataforma en wiki.wxpython.org que he probado con python 2.7 (instalación de minconda) en macOS High Sierra (10.13.3), Windows 7 y gnome 3 / centos7. Está aquí (ignora el título de la página): https://wiki.wxpython.org/Custom%20Mac%20OsX%20Dock%20Bar%20Icon

Se necesitan pequeños mods para python 3.6:

  • debes importar wx.adv
  • wx.TaskBarIcon se convierte en wx.adv.TaskBarIcon
  • wx.IconFromBitmap se convierte en wx.Icon

Gnome 3 requiere la instalación de TopIcons Plus.

Ya que no desea que se muestre la ventana (“no se muestra ninguna ventana, solo un icono de bandeja”), simplemente comente la siguiente línea (aunque todavía desea mantener el elemento primario wx.Frame):

 frame.Show(True) 

Y como desea usar su propio icono .png, elimine la imagen de WXPdemo y las imágenes de imágenes integradas y reemplace

 icon = self.MakeIcon(WXPdemo.GetImage()) 

con, por ejemplo

 icon = wx.Icon('icon.png') 

En mi experiencia, esto proporcionará un buen comienzo para adaptarse o extenderse más.