SystemTray
In addition to running normal windows, it's now also possible to have an icon down in the system tray that you can read to get menu events. There is a new SystemTray object that is used much like a Window object. You first get one, then you perform Reads in order to get events.
Tkinter versions
Simulated System Tray
While only PySimpleGUIQt and PySimpleGUIWx offer a true "system tray" feature, there is a simulated system tray feature that became available in 2020 for the tkinter port of PySimpleGUI. All of the same objects and method calls are the same and the effect is very similar to what you see with the Wx and Qt versions. The icon is placed in the bottom right corner of the window. Setting the location of it has not yet been exposed, but you can drag it to another location on your screen.
The idea of supporting Wx, Qt, and tkinter with the exact same source code is very appealing and is one of the reasons a tkinter version was developed. You can switch frameworks by simply changing your import statement to any of those 3 ports.
The balloons shown for the tkinter version is different than the message balloons shown by real system tray icons. Instead a nice semi-transparent window is shown. This window will fade in / out.
psgtray
Package
Another way of getting a System Tray icon in your PySimpleGUI program using the tkinter port is to add the psgtray
package to your installation. You'll find the psgtray package under the PySimpleGUI repo on GitHub. It can be pip installed just like PySimpleGUI can. Instructions on installing are in the project's readme.
This package does not contain as many features as the Qt and Wx port's System Tray feature, but there are enough to have a nice application available in the system tray. You will need to create a "parent window" for this architecture. If you don't want a visible window and only want a system tray icon, then make the window invisible (using the alpha channel for example).
SystemTray Object
You'll find the definition of the SystemTray object in the call reference for each of the PySimpleGUI ports. The psgtray
readme shows a design pattern that demonstrates the implemented features.
System Tray Design Pattern
Here is a design pattern you can use to get a jump-start when using the system tray built into the PySimpleGUI ports.
This program will create a system tray icon and perform a blocking Read. If the item "Open" is chosen from the system tray, then a popup is shown.
The same code can be executed on any of the Desktop versions of PySimpleGUI (tkinter, Qt, WxPython)
import PySimpleGUIQt as sg
# import PySimpleGUIWx as sg
# import PySimpleGUI as sg
menu_def = ['BLANK', ['&Open', '---', '&Save', ['1', '2', ['a', 'b']], '&Properties', 'E&xit']]
tray = sg.SystemTray(menu=menu_def, filename=r'default_icon.ico')
while True: # The event loop
menu_item = tray.read()
print(menu_item)
if menu_item == 'Exit':
break
elif menu_item == 'Open':
sg.popup('Menu item chosen', menu_item)
Icons
System Tray Icons are in PNG & GIF format when running on PySimpleGUI (tkinter version). PNG, GIF, and ICO formats will work for the Wx and Qt ports.
When specifying "icons", you can use 3 different formats.
* filename
- filename
* data_base64
- base64 byte string
* 'data
- in-ram bitmap or other "raw" image
You will find 3 parameters used to specify these 3 options on both the initialize statement and on the Update method.
For testing you may find using the built-in PySimpleGUI icon is a good place to start to make sure you've got everything coded correctly before bringing in outside image assets. It'll tell you quickly if you've got a problem with your icon file. To run using the default icon, use something like this to create the System Tray:
Menu Definition
A menu is defined using a list. A "Menu entry" is a string that specifies: * text shown * keyboard shortcut * key
See section on Menu Keys for more information on using keys with menus.
An entry without a key and keyboard shortcut is a simple string
'Menu Item'
If you want to make the "M" be a keyboard shortcut, place an &
in front of the letter that is the shortcut.
'&Menu Item'
You can add "keys" to make menu items unique or as another way of identifying a menu item than the text shown. The key is added to the text portion by placing ::
after the text.
'Menu Item::key'
The first entry can be ignored.'BLANK
' was chosen for this example. It's this way because normally you would specify these menus under some heading on a menu-bar. But here there is no heading so it's filled in with any value you want.
Separators
If you want a separator between 2 items, add the entry '---'
and it will add a separator item at that place in your menu.
Disabled menu entries
If you want to disable a menu entry, place a !
before the menu entry
SystemTray Methods
Read - Read the context menu or check for events
def Read(timeout=None)
'''
Reads the context menu
:param timeout: Optional. Any value other than None indicates a non-blocking read
:return: String representing meny item chosen. None if nothing read.
'''
timeout
parameter specifies how long to wait for an event to take place. If nothing happens within the timeout period, then a "timeout event" is returned. These types of reads make it possible to run asynchronously. To run non-blocked, specify timeout=0
on the Read call.
Read returns the menu text, complete with key, for the menu item chosen. If you specified Open::key
as the menu entry, and the user clicked on Open
, then you will receive the string Open::key
upon completion of the Read.
Read special return values
In addition to Menu Items, the Read call can return several special values. They include:
EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED - Tray icon was double clicked EVENT_SYSTEM_TRAY_ICON_ACTIVATED - Tray icon was single clicked EVENT_SYSTEM_TRAY_MESSAGE_CLICKED - a message balloon was clicked TIMEOUT_KEY is returned if no events are available if the timeout value is set in the Read call
hide
Hides the icon. Note that no message balloons are shown while an icon is hidden.
close
Does the same thing as hide
un_hide
Shows a previously hidden icon
show_message
Shows a balloon above the icon in the system tray area. You can specify your own icon to be shown in the balloon, or you can set messageicon
to one of the preset values.
This message has a custom icon.
The preset messageicon
values are:
SYSTEM_TRAY_MESSAGE_ICON_INFORMATION
SYSTEM_TRAY_MESSAGE_ICON_WARNING
SYSTEM_TRAY_MESSAGE_ICON_CRITICAL
SYSTEM_TRAY_MESSAGE_ICON_NOICON
Note, on windows it may be necessary to make a registry change to enable message balloons to be seen. To fix this, you must create the DWORD you see in this screenshot.
update
You can update any of these items within a SystemTray object * Menu definition * Icon * Tooltip
Change them all or just 1.
Notify Class Method
In addition to being able to show messages via the system tray, the tkinter port has the added capability of being able to display the system tray messages without having a system tray object defined. You can simply show a notification window. This perhaps removes the need for using the ptoaster package?
The method is a "class method" which means you can call it directly without first creating an instanciation of the object. To show a notification window, call SystemTray.notify
.
This line of code
Will show this window, fading it in and out:
This is a blocking call so expect it to take a few seconds if you're fading the window in and out. There are options to control the fade, how long things are displayed, the alpha channel, etc.. See the call signature at the end of this document.