Быстро и просто: трайкон с питоном? - PullRequest
30 голосов
/ 17 июня 2011

Мне просто нужен быстрый пример того, как легко разместить иконку с python на моей системной панели.Это означает: я запускаю программу, окно не отображается, просто в трее появляется иконка в трее (у меня есть файл png), и когда я щелкаю по нему правой кнопкой мыши, появляется меню с некоторыми опциями (и когда я нажимаюпо выбору, функция запускается).Это возможно?Мне вообще не нужно никаких окон ...

Примеры / фрагменты кода ДЕЙСТВИТЕЛЬНО приветствуются!: D

Ответы [ 8 ]

53 голосов
/ 17 июня 2011

Для Windows и Gnome

Вот, пожалуйста! wxPython - это бомба. Адаптировано из источника моего приложения 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()
12 голосов
/ 11 октября 2015

wx.PySimpleApp устарела, вот как использовать wx.App вместо

Мне потребовалось время, чтобы понять это, поэтому я решила поделиться.wx.PySimpleApp устарела в wxPython 2.9 и более поздних версиях.Вот оригинальный скрипт FogleBird, использующий вместо этого wx.App.

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()
4 голосов
/ 05 августа 2015

для 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)

Cross-Platform

См. PyQt: Показать меню в приложении на панели задач

4 голосов
/ 17 июня 2011

Если вы можете гарантировать Windows и не хотите вводить сильные зависимости от wx, вы можете сделать это с помощью pywin32 расширений .

Также смотрите этот вопрос .

3 голосов
/ 23 января 2018

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()
1 голос
/ 14 ноября 2013

Альтернатива, если вы пытаетесь запустить программу на основе Python в фоновом режиме, вы можете запустить ее как службу. Посмотрите этот рецепт активного состояния, он довольно полезен. Я считаю, что один из вариантов - преобразовать ваше приложение в exe с помощью py2exe или pyinstall.

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

0 голосов
/ 15 марта 2018

Да. На wiki.wxpython.org есть кроссплатформенный пример, который я тестировал с python 2.7 (установка minconda) на macOS High Sierra (10.13.3), Windows 7 и gnome 3 / centos7. Именно здесь (игнорируйте заголовок страницы): https://wiki.wxpython.org/Custom%20Mac%20OsX%20Dock%20Bar%20Icon

Для Python 3.6 нужны маленькие моды:

  • Вы должны импортировать wx.adv
  • wx.TaskBarIcon становится wx.adv.TaskBarIcon
  • wx.IconFromBitmap становится wx.Icon

Gnome 3 требует установки TopIcons Plus.

Поскольку вы не хотите, чтобы окно отображалось («окно не отображается, просто значок в трее»), просто закомментируйте следующую строку (хотя вы все еще хотите сохранить родительский элемент wx.Frame):

frame.Show(True)

И поскольку вы хотите использовать свой собственный значок .png, удалите изображение WXPdemo и встроенный образ и замените

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

с, например

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

По моему опыту, это станет хорошим началом для адаптации или расширения.

0 голосов
/ 08 марта 2018

Например, обратитесь к этой теме -> wx question.

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

...