usage.rst 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. Creating a *system tray icon*
  2. -----------------------------
  3. In order to create a *system tray icon*, the class ``pystray.Icon`` is used::
  4. import pystray
  5. icon = pystray.Icon('test name')
  6. In order for the icon to be displayed, you must provide an icon. This icon must
  7. be specified as a ``PIL.Image.Image``::
  8. from PIL import Image, ImageDraw
  9. def create_image():
  10. # Generate an image and draw a pattern
  11. image = Image.new('RGB', (width, height), color1)
  12. dc = ImageDraw.Draw(image)
  13. dc.rectangle(
  14. (width // 2, 0, width, height // 2),
  15. fill=color2)
  16. dc.rectangle(
  17. (0, height // 2, width // 2, height),
  18. fill=color2)
  19. return image
  20. icon.icon = create_image()
  21. To finally show you icon, run the following code::
  22. icon.run()
  23. The call to ``pystray.Icon.run()`` is blocking, and it must be performed from
  24. the main thread of the application. The reason for this is that the *system tray
  25. icon* implementation for *OSX* will fail unless called from the main thread, and
  26. it also requires the application runloop to be running. ``pystray.Icon.run()``
  27. will start the runloop.
  28. If you only target *Windows*, calling ``run()`` from a thread other than the
  29. main thread is safe.
  30. The ``run()`` method accepts an optional argument: ``setup``, a callable.
  31. The ``setup`` function will be run in a separate thread once the *system tray
  32. icon* is ready. The icon does not wait for it to complete, so you may put any
  33. code that would follow the call to ``pystray.Icon.run()`` in it.
  34. The call to ``pystray.Icon.run()`` will not complete until ``stop()`` is called.
  35. Getting input from the *system tray icon*
  36. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  37. In order to receive notifications about user interaction with the icon, a
  38. popup menu can be added with the ``menu`` constructor argument.
  39. This must be an instance of ``pystray.Menu``. Please see the reference for more
  40. information about the format.
  41. It will be displayed when the right-hand button has been pressed on the icon on
  42. *Windows*, and when the icon has been clicked on other platforms. Menus are not
  43. supported on *X*.
  44. Menus also support a default item. On *Windows*, and *X*, this item will be
  45. activated when the user clicks on the icon using the primary button. On other
  46. platforms it will be activated if the menu contains no visible entries; it does
  47. not have to be visible.
  48. All properties of menu items, except for the callback, can be dynamically
  49. calculated by supplying callables instead of values to the menu item
  50. constructor. The properties are recalculated every time the icon is clicked or
  51. any menu item is activated.
  52. If the dynamic properties change because of an external event, you must ensure
  53. that ``Icon.update_menu`` is called. This is required since not all supported
  54. platforms allow for the menu to be generated when displayed.
  55. Creating the menu
  56. ~~~~~~~~~~~~~~~~~
  57. *This is not supported on Xorg; please check Icon.HAS_MENU at runtime for
  58. support on the current platform.*
  59. A menu can be attached to a system tray icon by passing an instance of
  60. :class:`pystray.Menu` as the ``menu`` keyword argument.
  61. A menu consists of a list of menu items, optionally separated by menu
  62. separators.
  63. Separators are intended to group menu items into logical groups. They will not
  64. be displayed as the first and last visible item, and adjacent separators will be
  65. hidden.
  66. A menu item has several attributes:
  67. *text* and *action*
  68. The menu item text and its associated action.
  69. These are the only required attributes. Please see *submenu* below for
  70. alternate interpretations of *action*.
  71. *checked*
  72. Whether the menu item is checked.
  73. This can be one of three values:
  74. ``False``
  75. The item is decorated with an unchecked check box.
  76. ``True``
  77. The item is decorated with a checked check box.
  78. ``None``
  79. There is no hint that the item is checkable.
  80. If you want this to actually be togglable, you must pass a callable that
  81. returns the current state::
  82. from pystray import Icon as icon, Menu as menu, MenuItem as item
  83. state = False
  84. def on_clicked(icon, item):
  85. global state
  86. state = not item.checked
  87. # Update the state in `on_clicked` and return the new state in
  88. # a `checked` callable
  89. icon('test', create_image(), menu=menu(
  90. item(
  91. 'Checkable',
  92. on_clicked,
  93. checked=lambda item: state))).run()
  94. *radio*
  95. *This is not supported on macOS; please check Icon.HAS_MENU_RADIO at
  96. runtime for support on the current platform.*
  97. Whether this is a radio button.
  98. This is used only if ``checked`` is ``True`` or ``False``, and only has a
  99. visual meaning. The menu has no concept of radio button groups::
  100. from pystray import Icon as icon, Menu as menu, MenuItem as item
  101. state = 0
  102. def set_state(v):
  103. def inner(icon, item):
  104. global state
  105. state = v
  106. return inner
  107. def get_state(v):
  108. def inner(item):
  109. return state == v
  110. return inner
  111. # Let the menu items be a callable returning a sequence of menu
  112. # items to allow the menu to grow
  113. icon('test', create_image(), menu=menu(lambda: (
  114. item(
  115. 'State %d' % i,
  116. set_state(i),
  117. checked=get_state(i),
  118. radio=True)
  119. for i in range(max(5, state + 2))))).run()
  120. *default*
  121. *This is not supported on Darwin and using AppIndicator; please check
  122. Icon.HAS_DEFAULT at runtime for support on the current platform.*
  123. Whether this is the default item.
  124. It is drawn in a distinguished style and will be activated as the default
  125. item on platforms that support default actions. On *X*, this is the only
  126. action available.
  127. *visible*
  128. Whether the menu item is visible.
  129. *enabled*
  130. Whether the menu item is enabled. Disabled menu items are displayed, but are
  131. greyed out and cannot be activated.
  132. *submenu*
  133. The submenu, if any, that is attached to this menu item. Either a submenu
  134. or an action can be passed as the second argument to the constructor.
  135. The submenu must be an instance of :class:`Menu`::
  136. from pystray import Icon as icon, Menu as menu, MenuItem as item
  137. icon('test', create_image(), menu=menu(
  138. item(
  139. 'With submenu',
  140. menu(
  141. item(
  142. 'Submenu item 1',
  143. lambda icon, item: 1),
  144. item(
  145. 'Submenu item 2',
  146. lambda icon, item: 2))))).run()
  147. Once created, menus and menu items cannot be modified. All attributes except for
  148. the menu item callbacks can however be set to callables returning the current
  149. value. This also applies to the sequence of menu items belonging to a menu: this
  150. can be a callable returning the current sequence.
  151. Displaying notifications
  152. ~~~~~~~~~~~~~~~~~~~~~~~~
  153. *This is not supported on macOS and Xorg; please check Icon.HAS_NOTIFICATION
  154. at runtime for support on the current platform.*
  155. To display a system notification, use :meth:`pystray.Icon.notify`::
  156. from pystray import Icon as icon, Menu as menu, MenuItem as item
  157. icon('test', create_image(), menu=menu(
  158. item(
  159. 'With submenu',
  160. menu(
  161. item(
  162. 'Show message',
  163. lambda icon, item: icon.notify('Hello World!')),
  164. item(
  165. 'Submenu item 2',
  166. lambda icon, item: icon.remove_notification()))))).run()
  167. Integrating with other frameworks
  168. ---------------------------------
  169. The *pystray* ``run`` method is blocking, and must be called from the main
  170. thread to maintain platform independence. This is troublesome when attempting
  171. to use frameworks with an event loop, since they may also require running in
  172. the main thread.
  173. For this case you can use ``run_detached``. This allows you to setup the icon
  174. and then pass control to the framework. Please see the documentation for more
  175. information.
  176. Selecting a backend
  177. -------------------
  178. *pystray* aims to provide a unified *API* for all supported platforms. In some
  179. cases, however, that is not entirely possible.
  180. This library supports a number of backends. On *macOS* and *Windows*, the
  181. operating system has system tray icons built-in, so the default backends should
  182. be used, but on *Linux* you may have to make a decision depending on your
  183. needs.
  184. By setting the environment variable ``PYSTRAY_BACKEND`` to one of the strings in
  185. the next section, the automatic selection is turned off.
  186. Supported backends
  187. ~~~~~~~~~~~~~~~~~~
  188. *appindicator*
  189. This is one of the backends available on *Linux*, and is the preferred
  190. choice. All *pystray* features except for a menu default action are
  191. supported, and if the *appindicator* library is installed on the system
  192. and the desktop environment supports it, the icon is guaranteed to be
  193. displayed.
  194. If the *appindicator* library is not available on the system, a fallback on
  195. *ayatana-appindicator* is attempted.
  196. *darwin*
  197. This is the default backend when running on *macOS*. All *pystray* features
  198. are available.
  199. *gtk*
  200. This is one of the backends available on *Linux*, and is prioritised above
  201. the *XOrg* backend. It uses *GTK* as underlying library. All *pystray*
  202. features are available, but it may not actually result in a visible icon:
  203. when running a *gnome-shell* session, an third party plugin is required to
  204. display legacy tray icons.
  205. *win32*
  206. This is the default backend when running on *Windows*. All *pystray*
  207. features are available.
  208. *xorg*
  209. This is one of the backends available on *Linux*. It is used as a fallback
  210. when no other backend can be loaded. It does not support any menu
  211. functionality except for a default action.