Code Monkey home page Code Monkey logo

pystray's Introduction

pystray Package Documentation

This library allows you to create a system tray icon.

Supported platforms are Linux under Xorg, GNOME and Ubuntu, macOS and Windows.

See here for the full documentation.

pystray's People

Contributors

besser82 avatar lancekindle avatar moses-palmer avatar pauloacmartinez avatar pyhedgehog avatar ralphwetzel avatar simonlindholm avatar simonrob avatar sphh avatar superjamie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pystray's Issues

using pystray with PyInstaller produces No module named "pystray._win32" error

i have a very simple pystray program wich simply generates an image from a number and displays it in the tray however when using pyinstaller to compile it wich works with no errors. Then when i run it i get the error

Traceback (most recent call last):
  File "counter.py", line 1, in <module>
  File "c:\users\spitf\appdata\local\programs\python\python37\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 623, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\pystray\__init__.py, line 48, in <module>
  File "site-packages\pystray\__init__.py, line 45, in backend
ImportError: this platform is not supported: No module named "pystray._win32"
[129696] Failed to execute script counter

line 1 is import pystray
The error flashes up quickly the dissapears so ive tried my best to copy it down.
I am using windows 10 64 bit python 3.7 and pystray 0.16.0.
I have checked the site-packages folder and _win32 is there and i have pywin32 installed and the code works perfectly when not compiled. Any help would be appreciated

submenu not implented

On calling the method pystray.MenuItem() with the argument submenu one would get the following error:

TypeError: init() got an unexpected keyword argument 'submenu'

I have taken a look in the file _base.py which implements the above mentioned method and could not find any argument with the name submenu. Also there is no place where the method submenu is called...

Maybe this is also a misunderstanding but with the documentation I am not able to get this to work.

Bug when running headless and having Gtk3 installed

pystray never checks if the imported Gtk-class works like it tries in the xorg-class.
This means that projects like FlexGet crashes running headless on a machine where Gtk3 is installed: Flexget/Flexget#2633

The following logic is tested on both headless and desktop system.
The code however is only tested with flexget on a headless system.
So not proposed, needs more testing.

--- a/lib/pystray/_gtk.py
+++ b/lib/pystray/_gtk.py
@@ -24,6 +24,8 @@ from gi.repository import Gtk
 from ._util.gtk import GtkIcon, mainloop
 from ._util import serialized_image
 
+if not Gtk.init_check()[0]:
+   raise Exception("Gtk could not initialize")
 
 class Icon(GtkIcon):
     def __init__(self, *args, **kwargs):

Windows: Icon should self-repair on explorer restart

When explorer.exe (who is responsible for drawing Notification Area) restarts (i.e. after crash) icons of most applications shown, but not for pystray. I've found that there are specific message (TaskbarCreated) sent in this case. There are one problem - it's only broadcasted to top-level windows, so notification-only windows (with parent HWND_MESSAGE) doesn't receive it.

Finally: I've got a PR for this: #10

Cannot use bounded class method as action.

I put a pystray icon in my class:

import pystray
from PIL import Image

class MyIcon(object):
    def __init__(self):
        self.ico = Image.new('RGB', (16, 16), 'green')
        self.menu = pystray.Menu(pystray.MenuItem('Quit', self.quit))
        self.icon = pystray.Icon('TRAY', self.ico, 'title', self.menu)

    def run(self):
        self.icon.run()

    def quit(self, icon, item):
        # do something with self
        self.icon.stop()

myico = MyIcon()
myico.run()

I got an error on execution. It seems I cannot put bounded class method in the menu.

Traceback (most recent call last):
  File "D:\tmp\python\icon_test.py", line 17, in <module>
    myico = MyIcon()
  File "D:\tmp\python\icon_test.py", line 7, in __init__
    self.menu = pystray.Menu(pystray.MenuItem('Quit', self.quit))
  File "C:\Python27\lib\site-packages\pystray\_base.py", line 318, in __init__
    self._action = self._assert_action(action)
  File "C:\Python27\lib\site-packages\pystray\_base.py", line 428, in _assert_action
    raise ValueError(action)
ValueError: <bound method MyIcon.quit of <__main__.MyIcon object at 0x00000000045EC358>>

But if I remove the item argument from my class method like this:

    def quit(self, icon):
        # do something with self
        self.icon.stop()

The icon can be started on the tray, but once the quit menu is clicked an exception raise showing that my quit() method got too many arguments

ERROR:pystray._base:An error occurred when calling message handler
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\pystray\_win32.py", line 378, in _dispatcher
    uMsg, lambda w, l: 0)(wParam, lParam) or 0)
  File "C:\Python27\lib\site-packages\pystray\_win32.py", line 198, in _on_notify
    descriptors[index - 1](self)
  File "C:\Python27\lib\site-packages\pystray\_base.py", line 240, in inner
    callback(self)
  File "C:\Python27\lib\site-packages\pystray\_base.py", line 327, in __call__
    return self._action(icon, self)
TypeError: quit() takes exactly 2 arguments (3 given)

So, is there a way to make pystray working with my class?

Dynamic Icon

Is there any way to update the icon while its running? I've tried so hard but couldn't find any way to update it. I'm currently trying to code a CPU indicator. Here's my code:

import psutil
import pystray
from PIL import Image, ImageDraw, ImageFont
from threading import Thread


font = ImageFont.truetype('arial.ttf', 75)


def setup(icon):
    icon.visible = True


def exit_action(icon):
    icon.visible = False
    icon.stop()


def refresh_images():
    global blue_img
    blue_img = Image.new('RGB', (100, 100), color=(0, 0, 255))
    global red_img
    red_img = Image.new('RGB', (100, 100), color=(255, 0, 0))


def decide_bg(usage):
    if usage > 60:
        return red_img
    else:
        return blue_img


def decide_coords(usage):
    if usage < 10:
        return (32, 5)
    elif usage == 100:
        return (0, 5)
    else:
        return (5, 5)


def init_icon():
    usage = int(psutil.cpu_percent(interval=1))
    refresh_images()
    image = decide_bg(usage)
    coords = decide_coords(usage)

    d = ImageDraw.Draw(image)
    d.text(coords, str(usage), font=font, fill=(255, 255, 255))

    icon = pystray.Icon("usage", icon=image, title="CPU Usage")
    icon.menu = pystray.Menu(pystray.MenuItem('Exit', lambda : exit_action(icon)))
    icon.run()


thread = Thread(daemon=True, target=init_icon())

Simply, I need to find a way to update the icon each second, to be able to show the current CPU usage. I'm quite new to Python and I'd truly appreciate some help. Thanks in advance.

HAS_NOTIFICATION Is False!

Hello, Moses!

I've been developing on pystray for a little bit now and was excited to see the additions of notifications! That being said, I've tried to display one on Windows 10 (Notifications enabled) and HAS_NOTIFICATION is returning false! My code is below, perhaps I'm approaching it wrong?

import pystray
from PIL import Image
import io, base64

DEFAULT_BASE64_ICON = b'R0lGODlhIQAgAPcAAAAAADBpmDBqmTFqmjJrmzJsnDNtnTRrmTZtmzZumzRtnTdunDRunTRunjVvnzdwnzhwnjlxnzVwoDZxoTdyojhzozl0ozh0pDp1pjp2pjp2pzx0oj12pD52pTt3qD54pjt4qDx4qDx5qTx5qj16qj57qz57rD58rT98rkB4pkJ7q0J9rEB9rkF+rkB+r0d9qkZ/rEl7o0h8p0x9pk5/p0l+qUB+sEyBrE2Crk2Er0KAsUKAskSCtEeEtUWEtkaGuEiHuEiHukiIu0qKu0mJvEmKvEqLvk2Nv1GErVGFr1SFrVGHslaHsFCItFSIs1COvlaPvFiJsVyRuWCNsWSPsWeQs2SQtGaRtW+Wt2qVuGmZv3GYuHSdv3ievXyfvV2XxGWZwmScx2mfyXafwHikyP7TPP/UO//UPP/UPf/UPv7UP//VQP/WQP/WQf/WQv/XQ//WRP7XSf/XSv/YRf/YRv/YR//YSP/YSf/YSv/ZS//aSv/aS/7YTv/aTP/aTf/bTv/bT//cT/7aUf/cUP/cUf/cUv/cU//dVP/dVf7dVv/eVv/eV//eWP/eWf/fWv/fW/7cX/7cYf7cZP7eZf7dav7eb//gW//gXP/gXf/gXv/gX//gYP/hYf/hYv/iYf/iYv7iZP7iZf/iZv/kZv7iaP/kaP/ka//ma//lbP/lbv/mbP/mbv7hdP7lcP/ncP/nc//ndv7gef7gev7iff7ke/7kfv7lf//ocf/ocv/odP/odv/peP/pe//ofIClw4Ory4GszoSszIqqxI+vyoSv0JGvx5OxyZSxyZSzzJi0y5m2zpC10pi715++16C6z6a/05/A2qHC3aXB2K3I3bLH2brP4P7jgv7jh/7mgf7lhP7mhf7liv/qgP7qh/7qiP7rjf7sjP7nkv7nlv7nmP7pkP7qkP7rkv7rlv7slP7sl/7qmv7rnv7snv7sn/7un/7sqv7vq/7vrf7wpv7wqf7wrv7wsv7wtv7ytv7zvP7zv8LU48LV5c3a5f70wP7z0AAAACH5BAEAAP8ALAAAAAAhACAAAAj/AP8JHEiwoMGDCA1uoYIF4bhK1vwlPOjlQICLApwVpFTGzBk1siYSrCLgoskFyQZKMsOypRyR/GKYnBkgQbF/s8603KnmWkIaNIMaw6lzZ8tYB2cIWMo0KIJj/7YV9XgGDRo14gpOIUBggNevXpkKGCDsXySradSoZcMmDsFnDxpEKEC3bl2uXCFQ+7emjV83bt7AgTNroJINAq0wWBxBgYHHdgt0+cdnMJw5c+jQqYNnoARkAx04kPEvS4PTqBswuPIPUp06duzcuYMHT55wAjkwEahsQgqBNSQIHy582D9BePTs2dOnjx8/f1gJ9GXhRpTqApFQoDChu3cOAps///9D/g+gQvYGjrlw4cU/fUnYX6hAn34HgZMABQo0iJB/Qoe8UxAXOQiEg3wIXvCBQLUU4mAhh0R4SCLqJOSEBhhqkAEGHIYgUDaGICIiIoossogj6yBUTQ4htNgiCCB4oIJAtJTIyI2MOOLIIxMtQQIJIwQZpAgwCKRNI43o6Igll1ySSTsI7dOECSaUYOWVKwhkiyVMYuJlJpp0IpA6oJRTkBQopHnCmmu2IBA2mmQi5yZ0fgJKPP+0IwoooZwzkDQ2uCCoCywUyoIW/5DDyaKefOLoJ6LU8w87pJgDTzqmDNSMDpzqYMOnn/7yTyiglBqKKKOMUopA7JgCy0DdeMEjUDM71GqrrcH8QwqqqpbiayqToqJKLwN5g45A0/TAw7LL2krGP634aoopp5yiiiqrZLuKK+jg444uBIHhw7g+MMsDFP/k4wq22rririu4xItLLriAUxAQ5ObrwzL/0PPKu7fIK3C8uxz0w8EIIwzMP/cM7HC88hxEzBBCBGGxxT8AwQzDujws7zcJQVMEEUKUbPITAt1D78OSivSFEUXEXATKA+HTscC80CPSQNGEccQRYhjUDzfxcjPPzkgnLVBAADs='

def on_clicked(icon, item):
    if (icon.HAS_NOTIFICATION):
        icon.notify("Hey!")
    else:
        print("WAT")
    
class SystemTray:
    
    def create_image(self, b64):
        buffer = io.BytesIO(base64.b64decode(b64))
        img = Image.open(buffer)
        return img
        
    
    def __init__(self):
        
        self.MenuItems = []
        self.MenuItems.append(pysItem("Test", on_clicked))
        self.TrayIcon = pystray.Icon("Title", self.create_image(DEFAULT_BASE64_ICON))
        self.TrayIcon.menu = self.MenuItems
        
        self.TrayIcon.run()
        

SystemTray()

Thank you!

WIN XP sp3 Python 3.4

Help me , please , to find the proper pair of pystray/PIL version working on WinXPsp3 with Python 3.4 !
...'cause I'he got WinError messages - a lot. I'he tried to 'fix' the problem modifying lines in _win32.py module . Like this:

with serialized_image(self.icon, 'BMP') as icon_path:
self._icon_handle = win32.LoadImage(
None,
icon_path,
0,
16,
16,
win32.LR_LOADFROMFILE )

...but if I eliminate one error , I get the next one :) , like this:

Traceback (most recent call last):
File "C:\Python34\lib\threading.py", line 911, in _bootstrap_inner
self.run()
File "C:\Python34\lib\threading.py", line 859, in run
self._target(*self._args, **self._kwargs)
File "C:\Python34\NTPMON.pyw", line 44, in TRAY
icon.visible=True
File "C:\Python34\lib\site-packages\pystray_base.py", line 143, in visible
self._show()
File "C:\Python34\lib\site-packages\pystray_win32.py", line 76, in _show
szTip=self.title)
File "C:\Python34\lib\site-packages\pystray_win32.py", line 270, in _message
**kwargs))
File "C:\Python34\lib\site-packages\pystray_util\win32.py", line 192, in _err
raise ctypes.WinError()
OSError: [WinError 0]

Thanks for Your help !

update_menu is not thread-safe on macOS/win32

update_menu is meant to be called from the setup thread, but is currently unsafe to use on macOS/win32, since the main thread may be updating the menu at the same time. In addition, Cocoa requires that UI functions be called from the main thread.

Both implementations of _update_menu need to be changed to pass a message to the main thread, and do the real menu updates there.

macOS has similar problems with update_icon and update_title, and the win32 update_icon implementation should be reviewed as well (update_icon looks safe).

#59 fixed this for the GTK backend.

Title/name not working

Hi, first thanks for this easy to use tray icon!
I'm not sure if this is a bug or I didn't understand the parameter for name and title.
But if I hover over the icon, it only shows the name of the file not the title or name I assigned in the icon function.

I'm running KDE 5 and I forced to import Icon from _gtk (When using ._appindicator the default click won't work).

Thanks.

No default action on Windows

Hi.

Although one menu item of mine has the default flag set, nothing happens when I click on the icon.
I construct it like so:

menu = (item(localize('Open Type.World App'), openApp, default=True), item(localize('Check for font updates now'), checkForUpdates))
icon = pystray.Icon("Type.World", image, "Type.World", menu)

Is more code needed? This is how I understood it works.
(The default menu item does get rendered in bold in the menu, so something is happening for sure)

How icon.update_menu() works?

Hi,

I have a Menu as below for "Login". When the variable "loggedin" changes to True, neither with nor without update_menu(), the menu is not changing to "Logout". Any ideas please?

def on_monitor(icon, item):
    global state,loggedin
    state = not item.checked
    url = 'www.example.com'
    webbrowser.open_new_tab(url + '?i=' + str(uuid.uuid4()) )
    print("Waiting for login to complete")
    loggedin = True
    print("Logged In",icon.update_menu())
icon = pystray.Icon('Sample',title="Icons",menu=Menu(
    MenuItem(('Logout' if loggedin else 'Login'),on_monitor),
    MenuItem('Settings',on_settings),
    MenuItem('Sync',on_sync,checked=lambda item: state1),
    MenuItem('Exit',on_exit,checked=lambda item: state2)))

Menu is not appearing

Hi, I'm trying the next example, taken from here, and when I click the icon, the menu is not appearing. I have also try some very simple variation, but I don't know why the menu doesn't appear. I don't see any errors in my terminal, seems to be running fine. I've checked the documentation, but it seems like it should work right away.

from PIL import Image, ImageDraw

from pystray import Icon, Menu as menu, MenuItem as item


def image(color1, color2, width=64, height=64):
    result = Image.new('RGB', (width, height), color1)
    dc = ImageDraw.Draw(result)

    dc.rectangle((width // 2, 0, width, height // 2), fill=color2)
    dc.rectangle((0, height // 2, width // 2, height), fill=color2)

    return result


def on_activate(icon, quit):
    if quit:
        print('stopping...')
        icon.stop()
    else:
        print('doing nothing...')


def setup(icon):
    icon.visible = True


icon = Icon(
    'test',
    icon=image('white', 'black'),
    menu=menu(
        item(
            'Print',
            lambda icon: on_activate(icon, False)),
        menu.SEPARATOR,
        item(
            'Quit',
            lambda icon: on_activate(icon, True))))

icon.run(setup)

This is my system:

--------------------------------
OS: Ubuntu 17.10 x86_64
Host: Precision 5520
Kernel: 4.13.0-35-generic
Shell: bash 4.4.12
Resolution: 2048x1152
DE: GNOME
WM: GNOME Shell
WM Theme: Ambiance
Theme: Adapta [GTK2/3]
Icons: Numix-Circle [GTK2/3]
CPU: Intel i7-7700HQ (8) @ 3.800GHz
GPU: Intel HD Graphics 630
GPU: NVIDIA Quadro M1200 Mobile
Memory: 9144MiB / 32018MiB

Thanks a lot!

Submenu Documentation Clarity

Love this library, have just used it to speed up my development of a project. That said there are some holes in the submenu documentation. I understand you have no obligation to fix this, just thought I would put this forward for you to change at your discretion.

Submenus could use some clarification. I think it should be mentioned that you have to pass a Menu object in as the action of a menu item. Also adding submenu example code would be nice.

xorg tray icon has 1 pixel width

Hi,

When I use xorg tray icon, there is system tray icon but only with 1 pixel width. After digging I found that xembed windows with systray icon should contain size hints, something like

window.set_wm_normal_hints(
        flags=(Xlib.Xutil.PPosition | Xlib.Xutil.PSize | Xlib.Xutil.PMinSize),
        min_width=24,
        min_height=24
        )

Unclear icon setting

On Gtk icon. In you documentation is firstly created Icon() object without icon, which is set latter:

import pystray

icon = pystray.Icon('test name')
image = ...
icon.icon = image

This doesn't work (systray icon is not shown), because icon is not really set (_update_icon()) while visible is False, but one cannot set visible to True, until some image data are provided. Documentation tells to call show(), but Icon object has not show() method.

All works as expected, when i pass image into constructor, or when i set image twice, eg.::

icon.icon = image
icon.visible = True
icon.icon = image

or when i call _update:icon():

icon.icon = image
icon.visible = True
icon._update_icon()

Both workarounds are ugly.

How to terminate a script from the system tray menu

I tried the following code:

import pystray
import sys
import time
from PIL import Image
from pystray import Menu, MenuItem


def exit_action(icon):
    icon.visible = False
    sys.exit(0)


def init_icon():
    icon = pystray.Icon('mon')
    icon.menu = Menu(
        MenuItem('Exit', lambda : exit_action(icon)),
    )
    icon.icon = Image.open('icon.ico')
    icon.title = 'tooltip'

    def setup(icon):
        icon.visible = True

    icon.run(setup)

    return icon

icon = init_icon()

while True:
    time.sleep(5)

When I click on Exit menu item from the system tray menu Python shows exception instead of termination of the program:

An error occurred when calling message handler
Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\pystray\_win32.py", line 377, in _dispatcher
    uMsg, lambda w, l: 0)(wParam, lParam) or 0)
  File "C:\Python34\lib\site-packages\pystray\_win32.py", line 197, in _on_notify
    descriptors[index - 1](self)
  File "C:\Python34\lib\site-packages\pystray\_base.py", line 236, in inner
    callback(self)
  File "C:\Python34\lib\site-packages\pystray\_base.py", line 320, in __call__
    return self._action(icon, self)
  File "C:\Python34\lib\site-packages\pystray\_base.py", line 408, in wrapper0
    return action()
  File "C:\insolor\ะœะพะฝะธั‚ะพั€ะธะฝะณ\pstray_test.py", line 15, in <lambda>
    MenuItem('Exit', lambda : exit_action(icon)),
  File "C:\insolor\ะœะพะฝะธั‚ะพั€ะธะฝะณ\pstray_test.py", line 9, in exit_action
    sys.exit(0)
SystemExit: 0

After the exception the Python instance is still hanging in the task manager.

So how to terminate a program from the system tray menu?

System: Windows 10 Home (64 bit, ver 1511, build 10586.839)
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 20:20:57) [MSC v.1600 64 bit (AMD64)] on win32

Help: Strange error when using threading library

I'm getting this exception when I try to run an instance of pystray.
Iยดm creating a quit option that joins a thread and then does a sys.exit, what happens is this:

An error occurred when calling message handler
Traceback (most recent call last):
  File "C:\Python38\lib\site-packages\pystray\_win32.py", line 377, in _dispatcher
    return int(icon._message_handlers.get(
  File "C:\Python38\lib\site-packages\pystray\_win32.py", line 198, in _on_notify
    descriptors[index - 1](self)
  File "C:\Python38\lib\site-packages\pystray\_base.py", line 241, in inner
    callback(self)
  File "C:\Python38\lib\site-packages\pystray\_base.py", line 328, in __call__
    return self._action(icon, self)
  File "C:\Python38\lib\site-packages\pystray\_base.py", line 420, in wrapper0
    return action()
  File "tray3.py", line 42, in <lambda>
    item("Exit", lambda: make_me_stop())
  File "tray3.py", line 20, in make_me_stop
    sys.exit()
SystemExit

This is the code I'm working on:

import pystray
from PIL import Image
from pystray import MenuItem as item
import time
import sys
import threading


makemestop=False
icon="16/002-moon.png"

# the function to quit the program
def make_me_stop():
    print("I'm trying to stop")
    global makemestop
    makemestop=True
    my_x.join()
    icon.stop()
    print("I STOPPED!")
    sys.exit()

# This must go into another thread
def myloop():
    try:
        global icon
        icon="16/001-sun.png"
        while makemestop==False:
            print("I won't stop - ", makemestop)
            time.sleep(1)
    except:
        print("yass... I really stopped")

# this is the main thread
if __name__=="__main__":
    my_x=threading.Thread(target=myloop)
    my_x.start()

    image=Image.open(icon)

    menu=(
            item("Options", lambda: print("Call options")),
            item("Exit", lambda: make_me_stop())
    )

    icon=pystray.Icon("My icon title", image, "My icon title", menu)
    icon.run()

How to define a function on Icon doubleClick?

I found on documentation:

HAS_DEFAULT_ACTION = True
Whether this particular implementation has a default action that can be invoked in a special way, such as clicking on the icon.
https://pythonhosted.org/pystray/

But how can I define a default action to a pystray Icon?
When I click 2 times (double-click) on the tray icon, python console gets this error:

An error occurred when calling message handler Traceback (most recent call last): File "C:\Users\Matheus\PycharmProjects\limaApp\venv\lib\site-packages\pystray\_win32.py", line 377, in _dispatcher return int(icon._message_handlers.get( File "C:\Users\Matheus\PycharmProjects\limaApp\venv\lib\site-packages\pystray\_win32.py", line 175, in _on_notify self() File "C:\Users\Matheus\PycharmProjects\limaApp\venv\lib\site-packages\pystray\_base.py", line 84, in __call__ self._menu(self) TypeError: 'tuple' object is not callable

Here is my entire and simple App code:

from pystray import MenuItem as item
import pystray
from PIL import Image
import tkinter as tk


def quit_window(icon, item):
    icon.stop()
    window.destroy()


def show_window(icon, item):
    icon.stop()
    window.after(0, window.deiconify)


window = tk.Tk()
window.title("My App")
image = Image.open("assets/images/icon.ico")
menu = (item('My App', show_window, default=True), item('Sair', quit_window))
icon = pystray.Icon("name", image, "My App", menu)
icon.run()


def withdraw_window():
    print('Close window')
    window.withdraw()


window.protocol('WM_DELETE_WINDOW', withdraw_window)
window.mainloop()

Below the screen record:
ezgif com-video-to-gif

Anyone can help me?

Updating the menu when it's opened?

I would like to run update_menu() when the menu is opened.

I'm using a few of the menu items purely to display data - one of them is a filesize indicator. Currently the best way I've found is to just update the data every few seconds, but this isn't ideal and causes some responsiveness issues.

Is there an easy way of doing this?

Unable to quit program properly

Hello !

I try to have a menu item that call a close function.
But, the only thing that seems to be called in my close() function : trayicon.visible = False and trayicon.stop()

The sys.exit(0) call is not call.

There is something I do in the wrong way ?

My code :

import sys
import datetime
import pystray

from pynput import keyboard
from pystray import MenuItem as item
from PIL import Image

APP_NAME = 'ECS Shortcuts'
APP_VERSION = '1.0'

def shortcuts(trayicon):
	trayicon.visible = True
	current = set()
	
	def on_press(key):
		"""if any([key in COMBO for COMBO in COMBINATIONS]):
			current.add(key)
			if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
				listener.stop()"""
		if key == keyboard.Key.f8:
			execute()
	
	def on_release(key):
		"""if any([key in COMBO for COMBO in COMBINATIONS]):
			current.remove(key)"""
		pass
	
	with keyboard.Listener(on_press=on_press, 
						   on_release=on_release
	) as listener:
		listener.join()

def execute():
	date = datetime.datetime.now()
	day = date.day
	month = date.month
	if date.hour < 10:
		hour = '0' + str(date.hour)
	else:
		hour = date.hour
	if date.minute < 10:
		minute = '0' + str(date.minute)
	else:
		minute = date.minute
	kb = keyboard.Controller()
	kb.type("%s %s/%s %sh%s : " % (user, day,  month,  hour,  minute))

def close():
	trayicon.visible = False
	trayicon.stop()
	sys.exit(0)

if __name__ == '__main__':
	if len(sys.argv) > 1:
		user = sys.argv[1]
	else:
		user = ''

	name = ' '.join((APP_NAME, APP_VERSION))       
	icons = {
		'default': Image.open('icon.png')
	}       
	menu = (item('Quitter', close), )
	trayicon = pystray.Icon(name=name,
							icon=icons['default'],
							menu=menu,
							title=name
	)
	
	trayicon.icons = icons
	trayicon.warnings = True
	try:
		trayicon.run(shortcuts)
	except Exception as e:
		pass
	finally:
		trayicon.stop()
		sys.exit(0)

Thank in advance for any help,

Lucas

Feature request - scroll event

Hi, it will be possible to add scroll possibilities over the tray icon? Like when you use your mouse wheel to scroll up over icon, then you volume goes up ... ect. Thanks for answer.

Error in compiling with py2exe

I get following error in making a windows app.

        def setup(icon):
            icon.visible = True

File "pystray_base.pyo", line 153, in visible
File "pystray_win32.pyo", line 70, in _show
File "pystray_win32.pyo", line 323, in assert_icon_handle
File "contextlib.pyo", line 17, in enter
File "pystray_util_init
.pyo", line 42, in serialized_image
File "PIL\Image.pyo", line 1885, in save
KeyError: 'ICO'

Anyone faced this before?

Notifications do not work on Windows 8 32 bit

Hello Moses,
Thanks for new addition to pystray, I appreciate your work,
I already put "pystray" in latest version of my application "PyIDM", everything works great

I downloaded pystray from github and used the example you supplied but couldn't display notification, maybe i am doing something wrong

I am running windows 8-32 bit with python 3.6-32 bit

I am not expert in win32 API, but I think there is something mentioned in plyer balloon tip notification regarding registering a class first

here is plyer balloontip.py link:
https://github.com/kivy/plyer/blob/master/plyer/platforms/win/libs/balloontip.py

Also plyer has managed to send notification in linux too, if somehow pystray can do this it will be a great hit

the code i tried:

from pystray import Icon as icon, Menu as menu, MenuItem as item
from PIL import Image
import io, base64

APP_ICON2 = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKfSURB\nVDiNZdNfaNVlHAbwz/n9zu/M6Vz7o41yzplg4BCFolbZWi2FiBIMvQq9qJAuCokugqCWFAgJxSgS\n+kN5Uxb9uVJyVgc0wgg65UpczLl2HHPacM7z23bmOaeLnU6bvlcP7/s8z/d5X94n4Ya1dz3Fp9GF\n1vLmORzDB3T3zWcn/oc9VYy/hd3tssEWAxrErgmNqpHW6he3FnAAL9Cdn2fQU8X4keXiB/f7Vrus\nvFBOSiwSi8wI9Wv0pvuMq/4ej9CdD+cM7n5nmXj7576wsTaW7HpIPEtuqiBXCORErkoJlHT420nN\nq6cl60kfSZTvnPnYN8H9hjR8ckDdzh3Ge08I6m7y444XXTw3VkmSkzItaZ9NBYINIQ+83C7b/pyT\n8ktqBW1trmROyzy7V76YkGxeIZs5WxHHIqGiCYuCC5bMJPHwFgPyQqWWVv2v9ohFZmvrrdy51eFt\nLy0Qz+HF1rvgd02bA7Q0mhKLXDo9VCHd/voembcPuThyuSKeSVXLlc+TirAqQOmaxHUTIi3bugxn\nzspJKdXVe+y9PfZPfqnj+a1zCQVQSmJ4VM26+eJYZOzUgMe/3mes/7zGtSt99cqnzvx23rK1K8Qi\n0VyC4SR6f7B63T2GK+JY5ND217Q8usn4pdip42dM5BOeeONJhw/+pEZev0Y4GtKZHbF090ajQaBU\nMbiSDwz+MWJ48B+ThVAssripwWQ+ITk0qNeaAp4JSY/RefOvbrmrw5BJVTe8x3+4r2/MnctnfTTS\nZEbyXboPln9i57Ep0b0/a75tg1GBksuqF4iXmtFs0ocjTSYs+g67SBfKBukCnZ9NiepPWHXHVVVB\nvWlVCiJFoZK/NDpqTWFusl3XlWlBndsoPoXN5TonMFiu8/t0/zmf/S9tcxBW9J/R4gAAAABJRU5E\nrkJggg==\n'


def create_image():
    buffer = io.BytesIO(base64.b64decode(APP_ICON2))
    img = Image.open(buffer)
    return img


icon('test', create_image(), menu=menu(
    item(
        'With submenu',
        menu(
            item(
                'Show message',
                lambda icon, item: icon.notify('Hello World!')),
            item(
                'Submenu item 2',
                lambda icon, item: icon.remove_notification()))))).run()

How to stop icon run thread from the principale thread

hello,

Please help me, im using pystray to create an icon on my desktop, my purpose is how to change value of menuitem, i was thinking about stoping icon setup then updating icon menu before restart for a new time the icon setup. but i can't stop icon run, any idea please

Icon does not show up in system tray using example

Hi,
I'am trying to create an icon in the system tray using the provided example.
But here is my code:

from PIL import Image, ImageDraw
import pystray

print("Start")
icon = pystray.Icon('test name')
print("Step 1")

def create_image():
    # Generate an image and draw a pattern
    width=16
    height=16
    color1=50
    color2=250
    image = Image.new('RGB', (width, height), color1)
    dc = ImageDraw.Draw(image)
    dc.rectangle(
        (width // 2, 0, width, height // 2),
        fill=color2)
    dc.rectangle(
        (0, height // 2, width // 2, height),
        fill=color2)
    image.show()
    return image

icon.icon = create_image()
print("Step 2")
icon.run()
print("Step 3")

And the console output is:

Start
Step 1
Step 2

What am I doing wrong?

'checked' item not working properly when creating menu using lambda/for

I'm trying to create a menu with 'checked' items dynamically using lambda and for statements.

In the code, I have a function that returns the menu with a sub-menu built based in a dictionary named 'menu_notifications_active'.

The problem occurring is the checked item is only updated when I switch the last item ('Item5'). The action code is called correctly, but the code for the 'checked' property, for some reason, is not working as expected.

My code:

from pystray import Icon as tray_icon, Menu as menu, MenuItem as item

menu_notifications_active = {'Item1': True, 'Item2': True,
                             'Item3': True, 'Item4': True, 'Item5': True}

def check_item(icon, item):
    global menu_notifications_active
    menu_notifications_active[item.text] = not item.checked
    logger.info("Notification changed for {}: {}".format(
        item.text, menu_notifications_active[item.text]))

def get_item_value(key):
    logger.info("get_item_value('{}') = {}".format(
        key, menu_notifications_active[key]))
    return menu_notifications_active[key]

def create_menu():
    tray_menu = menu(item('Notifications', menu(
        lambda: (item(key, check_item, checked=lambda item: menu_notifications_active[key]) for key in menu_notifications_active))
    ), item('Exit', opt_exit))
    return tray_menu

def main():
    tray_icon.icon = create_image()
    tray_icon.menu = create_menu()
    sys.exit(0)

if __name__ == '__main__':
    main()

In the logs we can see:

  1. When app starts.
2019-07-25 12:55:23,345 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,345 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,345 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,345 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,345 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,346 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,346 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,346 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,346 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,346 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,347 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,347 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,347 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,348 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,348 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,348 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,348 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,348 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,348 [INFO] get_item_value('Item5') = True
2019-07-25 12:55:23,349 [INFO] get_item_value('Item5') = True
  1. When I check 'Item1'.
2019-07-25 12:56:41,182 [INFO] Notification changed for Item1: False
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,182 [INFO] get_item_value('Item5') = True
2019-07-25 12:56:41,197 [INFO] get_item_value('Item5') = True

  1. When I check 'Item5.
2019-07-25 12:57:20,437 [INFO] Notification changed for Item5: False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False
2019-07-25 12:57:20,437 [INFO] get_item_value('Item5') = False

Thanks in advance!

Left Click Not Work

Here my codes:

def quit_window(self):
    self.icon.stop()
    self.exitMain()

def show_window(self):
    self.icon.stop()
    self.mainWindow.after(0, self.mainWindow.deiconify)
    keyboard.add_hotkey(self.keyShortcut, self.runRecongnizer)

def withdraw_window(self):
    keyboard.unhook_all_hotkeys()
    self.mainWindow.withdraw()
    image = PIL.Image.open("resources/media/image/favicon.ico")
    menu = (pystray.MenuItem(lang().translate("Show"), lambda: self.show_window()),
            pystray.MenuItem(lang().translate("Exit"), lambda: self.quit_window()))
    self.icon = pystray.Icon("name", image, "My Program", menu)
    self.icon.run()

When I left-clicking the system tray icon, I get this error:

An error occurred when calling message handler Traceback (most recent call last): File "C:\Users\MEmin\AppData\Local\Programs\Python\Python35-32\lib\site-packages\pystray\_win32.py", line 378, in _dispatcher uMsg, lambda w, l: 0)(wParam, lParam) or 0) File "C:\Users\MEmin\AppData\Local\Programs\Python\Python35-32\lib\site-packages\pystray\_win32.py", line 175, in _on_notify self() File "C:\Users\MEmin\AppData\Local\Programs\Python\Python35-32\lib\site-packages\pystray\_base.py", line 83, in __call__ self._menu(self) TypeError: 'tuple' object is not callable

Documentation error on http://pythonhosted.org/pystray/

In the second code snippet,

from PIL import Image, ImageDraw

# Generate an image
image = Image.new('RGB', (width, height), color1)
dc = ImageDraw.Draw(image)
dc.rectangle((width // 2, 0, width, height // 2), fill=color2)
dc.rectangle((0, height // 2, width // 2, height), fill=color2)

icon.image = image

change icon.image = image to icon.icon = image

MacOSX - Error: 'Icon' object has no attribute '_delegate'

I am trying to run the sample app on Mac OS mojave. But I get the following error. The icon runs fine though. Can someone please help.


Error: 'Icon' object has no attribute '_delegate'
Traceback (most recent call last):
  File "test.py", line ***
    icon.update_menu()
  File "/usr/local/lib/python3.7/site-packages/pystray/_base.py", line 213, in update_menu
    self._menu_handle = self._create_menu_handle()
  File "/usr/local/lib/python3.7/site-packages/pystray/_darwin.py", line 70, in _create_menu_handle
    nsmenu = self._create_menu(self.menu, callbacks)
  File "/usr/local/lib/python3.7/site-packages/pystray/_darwin.py", line 190, in _create_menu
    self._create_menu_item(descriptor, callbacks))
  File "/usr/local/lib/python3.7/site-packages/pystray/_darwin.py", line 219, in _create_menu_item
    menu_item.setTarget_(self._delegate)
AttributeError: 'Icon' object has no attribute '_delegate'

PIL dependency simplification

Hi great project i really appreciate any modules that add basic functions to Python while keeping it cross-platform.
I'd like to "feature" request that you remove the dependency on PIL and allow for usage of an icon.png file. Hope i'm not alone in this desire, that it sounds reasonible and hope that it is easy to implement.

Error when using remove_notification() in Linux

Kubuntu 20.04 (plasma)

(main.py:1070695): libappindicator-WARNING **: 19:01:17.474: Using '/tmp' paths in SNAP environment will lead to unreadable resources
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gi/overrides/GLib.py", line 130, in _create
    iter(value)
TypeError: 'int' object is not iterable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/www/anbcoder/.venv/lib/python3.8/site-packages/pystray/_base.py", line 267, in inner
    callback(self)
  File "/www/anbcoder/.venv/lib/python3.8/site-packages/pystray/_base.py", line 368, in __call__
    return self._action(icon, self)
  File "/www/anbcoder/main.py", line 65, in <lambda>
    lambda icon, item: icon.remove_notification()))))).run()
  File "/www/anbcoder/.venv/lib/python3.8/site-packages/pystray/_base.py", line 239, in remove_notification
    self._remove_notification()
  File "/www/anbcoder/.venv/lib/python3.8/site-packages/pystray/_util/gtk.py", line 84, in _remove_notification
    self._notifier.hide()
  File "/www/anbcoder/.venv/lib/python3.8/site-packages/pystray/_util/notify_dbus.py", line 89, in hide
    GLib.Variant(
  File "/usr/lib/python3/dist-packages/gi/overrides/GLib.py", line 189, in __new__
    v = creator._create(format_string, value)
  File "/usr/lib/python3/dist-packages/gi/overrides/GLib.py", line 132, in _create
    raise TypeError("Could not create array, tuple or dictionary entry from non iterable value %s %s" %
TypeError: Could not create array, tuple or dictionary entry from non iterable value (u) 83

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

I'm running exactly the code from the documentation example:

icon('test', Image.open(r'myproject-favicon.png'), menu=menu(
    item(
        'With submenu',
        menu(
            item(
                'Show message',
                lambda icon, item: icon.notify('Hello World!')),
            item(
                'Submenu item 2',
                lambda icon, item: icon.remove_notification()))))).run()

The tray shows up, the hello world notification shows up, but when pressing the remove notification button, it gives me this error and nothing happens.

Default action after left click on tray icon

I am using Gnome 3 and for my app I would like to have really simple function for tray icon: if I click on icon, the app will show its window, if I click on tray icon again, the app will hide its window. I can do this, but not just with click, just with menu - but I want no menu, just click. Double click dont work too. Still will just open menu. But if I click on menu item, it is working good, but I would like to work without menu.
Here is my code:

from` pystray import Icon as icon, Menu as menu, MenuItem as item
from PIL import Image, ImageDraw, ImageFont
import time

def create_image():
    # Generate an image and draw a pattern
    font = ImageFont.truetype("/usr/share/fonts/liberation/LiberationSans-Regular.ttf", 90)
    img = Image.new("RGB", (100, 100), "white")
    img.putalpha(0)
    d = ImageDraw.Draw(img)
    d.text((0,0), "50", font=font, fill='red')

    return img

from kivy.clock import Clock
from kivy.app import App
from kivy.config import Config
from kivy.uix.textinput import TextInput
from threading import Thread

Config.set('graphics', 'window_state', 'hidden')
Config.set('graphics', 'borderless', '1')
Config.set('kivy', 'exit_on_escape', '0')

class MyDebugApp(App):
    visible = False
    def build(self):
        return TextInput()
    
    def on_start(self):
        self.root.focus = True    

    def alternate(self):
        if self.visible:
            self.root.get_root_window().hide()
        else:
            self.root.get_root_window().show()

        self.visible = not self.visible

ma = MyDebugApp()       
kivy_app = Thread(target=ma.run)
kivy_app.start()

my_menu = menu(item(text="Show Main Window", action=ma.alternate, default = True, visible=False))
icon = icon('EasyBright', create_image(), menu=my_menu)
icon.run()

Icon image left in /tmp

I am dynamically updating the icon image in a thread as suggested in #30 and it works well. Thank you.

During runtime a copy of the current image is created with a random name at /tmp/tmp*. Each time the icon changes, it appears the old file is deleted and a new file is created with a new random name.

However, each time the below code is run, a copy of the icon image is left behind on exit. If the script runs 100 times, then 100 temporary files are left behind.

It seems there is something missing in cleanup of the icon image on exit?

This code tests whether a VPN network interface is up or not, however you can change the path to any test file then create and delete that test file to test the functionality. The actual VPN does not matter. I am using Ubuntu 18.04.

#!/usr/bin/python3

import os
import time
from PIL import Image
from pystray import Icon, Menu, MenuItem
from threading import Thread

path = "/sys/class/net/tun0/operstate"

imagedn = Image.open("/usr/share/icons/gnome/16x16/status/user-busy.png")
imageup = Image.open("/usr/share/icons/gnome/16x16/status/user-available.png")

def check_vpn(icon):
    while True:
        if os.path.isfile(path):
            if icon.icon is not imageup:
                icon.icon = imageup
        else:
            if icon.icon is not imagedn:
                icon.icon = imagedn
        time.sleep(0.5)

def loop(icon):
    icon.visible = True
    thread = Thread(target=check_vpn, args=([icon]), daemon=True)
    thread.start()

def exit_action(icon):
    icon.stop()

icon = Icon(name="VPN Status Icon", icon=imagedn, menu=Menu(MenuItem("Exit", lambda : exit_action(icon))))
icon.run(setup=loop)

How pass Menu later to Icon?

I want to declare Icon and provide menu later. I intend to pass icon explicitly along with some other variables to act on extra variables using user actions.

This platform is not supported

I directly imported pystray after installing with pip3

ImportError: this platform is not supported

I'm currently on ubuntu.
Doing a little digging, I went through the imports one by one and found Xlib is not installed.

pip3 install python3-xlib

ah... I think I see how this is a problem.
Since python-xlib does not install on python3,
and python3-xlib does not installl on python2,
trying to create a universal pystray will fail since you can't require the same type of packages.

I think getting a more informative error (in case an import fails) would be useful.

Integration with GUI frameworks

I'd like to open a window when a menu on the icon is clicked.

I've been playing around with tk, but I have a hard time getting tk and pystray to work at the same time since both assume that they control the event loop.

Do you have any recommendations how I could make this work?

AssertionError on Elementary OS and python3.6

mbarkhau@mbarkhau-vbox:~/pystray$ python3 -m unittest tests/icon_tests.py 
/usr/local/lib/python3.6/site-packages/Xlib/xauth.py:45: ResourceWarning: unclosed file <_io.BufferedReader name='/home/mbarkhau/.Xauthority'>
  raw = open(filename, 'rb').read()
/usr/local/lib/python3.6/site-packages/Xlib/protocol/rq.py:1012: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
  v, l, fm = f.pack_value(field_args[f.name])
/usr/local/lib/python3.6/site-packages/Xlib/protocol/rq.py:707: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
  data, dlen, fmt = PropertyData.pack_value(self, value)
Failed to dock icon
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/pystray/_xorg.py", line 140, in _show
    self._assert_docked()
  File "/usr/local/lib/python3.6/site-packages/pystray/_xorg.py", line 385, in _assert_docked
    assert self._systray_manager
AssertionError


Click the icon

How to run the icon app from a thread? Accessviolation error

Hi,

I am trying to run the app from a thread.
There is a random error(happens 8 of 10 times).
WindowsError: exception: access violation reading 0x00007FFC0000C2FD
I am sharing the icon with other threads via globals. So have to initialize it with
icon = None

I suspect this is the reason, where a main thread variable is being used by sub-threads.

How to overcome?

A trycatch points to

Error: exception: access violation reading 0x00007FFC0000C2FD
Traceback (most recent call last):
File "pystrayTest.py", line 366, in run_icon
MenuItem('Exit',on_exit)))
File "C:\Python27\lib\site-packages\pystray_win32.py", line 60, in init
self._menu_hwnd = self._create_window(self._atom)
File "C:\Python27\lib\site-packages\pystray_win32.py", line 226, in _create_w
indow
None)
WindowsError: exception: access violation reading 0x00007FFC0000C2FD

Support for icon tooltip and "Double-click" event

Hello,
Thanks for this outstanding work, this is a nice cross-platform and lightweight package,

I was looking for a lightweight systray that can work with tkinter and yours was my first choice until i found something in documentation says that pystray must run from main loop, then i decided to use "infi.systray" which supports windows only, everything works on windows flawlessly no issues,

Then i tried to find a way to run your pystray from a thread, and finally it did work "I didn't know before that main thread is the requirement for mac only", and i have to create menu and run icon from same thread.

everything works well with pystray on windows, however i miss 2 features:
1- set/update tooltip, in infi.systray i can use systray.update(hover_text='my tooltip')
2- Double-click

which, I hope you could add support for both.

here is an example code, where I run Icon from a thread "not worry about mac support right now"

from PIL import Image
import threading, io, base64
from pystray import Icon, Menu, MenuItem

APP_ICON2 = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKfSURB\nVDiNZdNfaNVlHAbwz/n9zu/M6Vz7o41yzplg4BCFolbZWi2FiBIMvQq9qJAuCokugqCWFAgJxSgS\n+kN5Uxb9uVJyVgc0wgg65UpczLl2HHPacM7z23bmOaeLnU6bvlcP7/s8z/d5X94n4Ya1dz3Fp9GF\n1vLmORzDB3T3zWcn/oc9VYy/hd3tssEWAxrErgmNqpHW6he3FnAAL9Cdn2fQU8X4keXiB/f7Vrus\nvFBOSiwSi8wI9Wv0pvuMq/4ej9CdD+cM7n5nmXj7576wsTaW7HpIPEtuqiBXCORErkoJlHT420nN\nq6cl60kfSZTvnPnYN8H9hjR8ckDdzh3Ge08I6m7y444XXTw3VkmSkzItaZ9NBYINIQ+83C7b/pyT\n8ktqBW1trmROyzy7V76YkGxeIZs5WxHHIqGiCYuCC5bMJPHwFgPyQqWWVv2v9ohFZmvrrdy51eFt\nLy0Qz+HF1rvgd02bA7Q0mhKLXDo9VCHd/voembcPuThyuSKeSVXLlc+TirAqQOmaxHUTIi3bugxn\nzspJKdXVe+y9PfZPfqnj+a1zCQVQSmJ4VM26+eJYZOzUgMe/3mes/7zGtSt99cqnzvx23rK1K8Qi\n0VyC4SR6f7B63T2GK+JY5ND217Q8usn4pdip42dM5BOeeONJhw/+pEZev0Y4GtKZHbF090ajQaBU\nMbiSDwz+MWJ48B+ThVAssripwWQ+ITk0qNeaAp4JSY/RefOvbrmrw5BJVTe8x3+4r2/MnctnfTTS\nZEbyXboPln9i57Ep0b0/a75tg1GBksuqF4iXmtFs0ocjTSYs+g67SBfKBukCnZ9NiepPWHXHVVVB\nvWlVCiJFoZK/NDpqTWFusl3XlWlBndsoPoXN5TonMFiu8/t0/zmf/S9tcxBW9J/R4gAAAABJRU5E\nrkJggg==\n'

def create_image():
	buffer = io.BytesIO(base64.b64decode(APP_ICON2))
	img = Image.open(buffer)
	return img

def quit(icon, item):
	icon.stop()

def show():
	print('show main window')

def create_icon():
	# i can use one click using default=True, but no option for double-click
	menu = Menu(MenuItem("Start / Show", show, default=True), MenuItem("Minimize to Systray", 
		lambda: None), MenuItem("Close to Systray", lambda: None), MenuItem("Quit", quit))
	icon = Icon('test', create_image(), menu=menu)
	return icon

def foo():
	print('start icon')
	icon = create_icon()
	icon.run()
		
threading.Thread(target=foo).start()

Icon goes missing from the system tray

Hi guys,

I am facing an issue where my application goes missing from the system tray, but it is running properly when viewing in task manager. The issue is not persistent . If I restart my application trayicon appears again.

This is my code to make the icon visible.

icon = pystray.Icon('test name')
icon.visible = True

This is the stack trace of the error which I guess is the root of the issue

  File "C:\Python34\lib\site-packages\pystray\_base.py", line 153, in visible
    self._show()
  File "C:\Python34\lib\site-packages\pystray\_win32.py", line 75, in _show
    szTip=self.title)
  File "C:\Python34\lib\site-packages\pystray\_win32.py", line 296, in _message
    **kwargs))
OSError: exception: access violation reading 0x00000000049D1008.

This is the function which fails

win32.Shell_NotifyIcon(code, win32.NOTIFYICONDATA(
            cbSize=ctypes.sizeof(win32.NOTIFYICONDATA),
            hWnd=self._hwnd,
            hID=id(self),
            uFlags=flags,
            **kwargs))

Please help me to resolve the issue.

Thanks

Is _running set wrongly?

I'm spelunking through the library source in hopes of finding the reason for a mysterious GTK crash... and saw something weird:

    def run(self, setup=None):
        ...
        self._run()
        self._running = True

_run() only returns once stop() is called, so if stop() is called from the setup thread, it will first set _running to False, and then run() will set it back to True after _run() returns.

_running is later used in __del__ in _win32.py and _xorg.py to decide whether to call stop().

I suspect this is unintended, though I'm not able to test on Windows to tell what the effects of changing it would be.

Icon.Notify does not work

Hello again!

The latest update did, indeed, fix the HAS_NOTIFICATION issue. Thank you for the quick fix! :)

However, I run into an issue where no error is reported, but a notification is not displayed.

This can be reproduced by simply putting icon.Notify("msg") in the setup callback.

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.