python wxpython pyqt systray tray

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



wxpython pyqt (8)

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()

Solo necesito un ejemplo rápido sobre cómo colocar fácilmente un icono con python en mi bandeja del sistema. Esto significa: ejecuto el programa, no aparece ninguna ventana, solo un icono de la bandeja (tengo un archivo png) aparece en la bandeja del sistema y cuando hago clic con el botón derecho 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 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 [email protected]") 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.


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()


Para un ejemplo, consulte este hilo -> wx pregunta.

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:

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

Gnome 3 requirió 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 aún 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.


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

También vea esta question .


Una alternativa si está intentando ejecutar un programa 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/


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()