Creating a system tray icon¶
In order to create a system tray icon, the class pystray.Icon
is used:
import pystray
from PIL import Image, ImageDraw
def create_image(width, height, color1, color2):
# Generate an image and draw a pattern
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)
return image
# In order for the icon to be displayed, you must provide an icon
icon = pystray.Icon(
'test name',
icon=create_image(64, 64, 'black', 'white'))
# To finally show you icon, call run
icon.run()
The call to pystray.Icon.run()
is blocking, and it must be performed from
the main thread of the application. The reason for this is that the system tray
icon implementation for OSX will fail unless called from the main thread, and
it also requires the application runloop to be running. pystray.Icon.run()
will start the runloop.
If you only target Windows, calling run()
from a thread other than the
main thread is safe.
The run()
method accepts an optional argument: setup
, a callable.
The setup
function will be run in a separate thread once the system tray
icon is ready. The icon does not wait for it to complete, so you may put any
code that would follow the call to pystray.Icon.run()
in it.
The call to pystray.Icon.run()
will not complete until stop()
is called.
Getting input from the system tray icon¶
In order to receive notifications about user interaction with the icon, a
popup menu can be added with the menu
constructor argument.
This must be an instance of pystray.Menu
. Please see the reference for more
information about the format.
It will be displayed when the right-hand button has been pressed on the icon on Windows, and when the icon has been clicked on other platforms. Menus are not supported on X.
Menus also support a default item. On Windows, and X, this item will be activated when the user clicks on the icon using the primary button. On other platforms it will be activated if the menu contains no visible entries; it does not have to be visible.
All properties of menu items, except for the callback, can be dynamically calculated by supplying callables instead of values to the menu item constructor. The properties are recalculated every time the icon is clicked or any menu item is activated.
If the dynamic properties change because of an external event, you must ensure
that Icon.update_menu
is called. This is required since not all supported
platforms allow for the menu to be generated when displayed.
Displaying notifications¶
This is not supported on macOS and Xorg; please check Icon.HAS_NOTIFICATION at runtime for support on the current platform.
To display a system notification, use pystray.Icon.notify()
:
from pystray import Icon as icon, Menu as menu, MenuItem as item
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()
Integrating with other frameworks¶
The pystray run
method is blocking, and must be called from the main
thread to maintain platform independence. This is troublesome when attempting
to use frameworks with an event loop, since they may also require running in
the main thread.
For this case you can use run_detached
. This allows you to setup the icon
and then pass control to the framework. Please see the documentation for more
information.
Selecting a backend¶
pystray aims to provide a unified API for all supported platforms. In some cases, however, that is not entirely possible.
This library supports a number of backends. On macOS and Windows, the operating system has system tray icons built-in, so the default backends should be used, but on Linux you may have to make a decision depending on your needs.
By setting the environment variable PYSTRAY_BACKEND
to one of the strings in
the next section, the automatic selection is turned off.
Supported backends¶
- appindicator
This is one of the backends available on Linux, and is the preferred choice. All pystray features except for a menu default action are supported, and if the appindicator library is installed on the system and the desktop environment supports it, the icon is guaranteed to be displayed.
If the appindicator library is not available on the system, a fallback on ayatana-appindicator is attempted.
- darwin
- This is the default backend when running on macOS. All pystray features are available.
- gtk
- This is one of the backends available on Linux, and is prioritised above the XOrg backend. It uses GTK as underlying library. All pystray features are available, but it may not actually result in a visible icon: when running a gnome-shell session, an third party plugin is required to display legacy tray icons.
- win32
- This is the default backend when running on Windows. All pystray features are available.
- xorg
- This is one of the backends available on Linux. It is used as a fallback when no other backend can be loaded. It does not support any menu functionality except for a default action.