J'aurais juste besoin d'un exemple rapide sur la façon de mettre facilement une icône avec python sur ma barre d'état système. Cela signifie: j'exécute le programme, aucune fenêtre ne s'affiche, juste une icône de plateau (I ' ai un fichier png) apparaît dans le systray et quand je clique dessus avec le bouton droit un menu apparaît avec quelques options (et quand je clique sur une option, une fonction est exécutée). Est-ce possible? Je n'ai besoin d'aucun fenêtre du tout ...
Les exemples/extraits de code sont vraiment appréciés! :RÉ
Voilà! wxPython est la bombe. Adapté de la source de mon application 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()
Cela m'a pris du temps pour comprendre cela, alors j'ai pensé partager. wx.PySimpleApp est déconseillé dans wxPython 2.9 et au-delà. Voici le script original de FogleBird utilisant wx.App à la place.
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()
Version 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()
Si vous pouvez garantir des fenêtres et que vous ne voulez pas introduire les fortes dépendances de wx, vous pouvez le faire avec les extensions pywin32 .
Voir aussi ceci question .
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)
Voir PyQt: Afficher le menu dans une application de la barre d'état système
Oui. Il y a un exemple multiplateforme sur wiki.wxpython.org que j'ai testé avec python 2.7 (installation de minconda) sur macOS High Sierra (10.13.3), Windows 7 et gnome 3/centos7. Il est ici (ignorez le titre de la page): https://wiki.wxpython.org/Custom%20Mac%20OsX%20Dock%20Bar%20Icon
De petits mods sont nécessaires pour python 3.6:
Gnome 3 a nécessité l'installation de TopIcons Plus.
Puisque vous ne voulez pas que la fenêtre s'affiche ("aucune fenêtre n'apparaît, juste une icône de plateau"), commentez simplement la ligne suivante (bien que vous souhaitiez toujours conserver le parent wx.Frame):
frame.Show(True)
Et puisque vous souhaitez utiliser votre propre icône .png, supprimez l'image WXPdemo et les images intégrées et remplacez
icon = self.MakeIcon(WXPdemo.GetImage())
avec, par exemple
icon = wx.Icon('icon.png')
D'après mon expérience, cela constituera un bon point de départ pour s'adapter ou s'étendre davantage.
Une alternative si vous essayez d'exécuter un programme basé sur python en arrière-plan, vous pouvez l'exécuter en tant que service. Découvrez cette recette d'état actif, c'est assez utile. Je crois qu'une des options est de convertissez votre application en exe avec py2exe ou pyinstall.
Pour un exemple, reportez-vous à ce fil -> question wx.
wxPython "classic" -> [new API] wxPython 'Phoenix' (Py3)