A lightweight Python library for creating system tray icons on Windows. (Future versions will add macOS and Linux support.) No heavy GUI dependencies—just simple status indicators, notifications, and menus.
Project description
CrossTray
A lightweight, unified Python library for creating system tray/menu bar icons across Windows, macOS, and Linux. No heavy GUI dependencies—just pure Python simplicity for status indicators, notifications, and menus.
Why CrossTray?
- Cross-Platform Magic: Handles OS-specific quirks automatically (e.g., Windows notification area, macOS menu bar, Linux systray).
- Minimal Footprint: Dependency-free core (uses stdlib where possible, optional extras for icons/notifications).
- Easy API: Object-oriented and chainable, inspired by
pathlibfor intuitive use. - Async-Friendly: Supports asyncio for real-time updates without blocking.
Perfect for building desktop utilities like monitors, trackers, or background apps.
Installation
pip install crosstray
Quick Start
from crosstray import Tray
tray = Tray(icon="path/to/icon.png", title="My App")
tray.add_menu_item("Quit", lambda: tray.quit())
tray.run()
For more examples, see Usage.
Features
- Create tray icons with custom images or text fallbacks.
- Build nested menus with callbacks.
- Show balloon notifications/toasts.
- Dynamic updates (e.g., change icon or menu on the fly).
- Event loop integration for async apps.
- Error handling for unsupported platforms.
Usage
Basic Tray Icon
from crosstray import Tray
def on_click(tray: ct.Tray):
tray.send_notification("Tray Clicked", "You clicked the tray icon!", icon="file.ico", timeout=9000)
tray = Tray(icon="icon.ico", tooltip="Hello World")
tray.on_click = tray.on_click = lambda: on_click(tray) # Or use tray.add_action("Click", on_click)
tray.run() # Blocks until quit
With Menu
from crosstray import Tray, MenuItem
tray = Tray(title="Status Monitor")
menu = tray.menu
menu.add_item(MenuItem("Refresh", lambda: print("Refreshing...")))
menu.add_separator()
submenu = menu.add_submenu("Settings")
submenu.add_item(MenuItem("Option 1", lambda: print("Selected 1")))
menu.add_item(MenuItem("Quit", tray.quit))
tray.run()
Async Example
import asyncio
from crosstray import Tray
async def main():
tray = Tray(icon="icon.png")
tray.add_menu_item("Update", lambda: print("Updating"))
# Simulate real-time update
async def updater():
while True:
tray.tooltip = f"Time: {asyncio.get_event_loop().time()}"
await asyncio.sleep(1)
asyncio.create_task(updater())
await tray.run_async() # Non-blocking
asyncio.run(main())
Contributing
Contributions welcome! Fork the repo, create a branch, and submit a PR. See CONTRIBUTING.md for guidelines.
License
MIT License. See LICENSE for details.
Built with ❤️ by Uman Sheikh. Inspired by community needs for simpler desktop tools.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file crosstray-0.1.1.tar.gz.
File metadata
- Download URL: crosstray-0.1.1.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52f20acf83534907aebaf6fb3fa78a66e35ab35584411bb6c5c398e9c1944638
|
|
| MD5 |
6d6a431d5846ba40757641dcde78ff6d
|
|
| BLAKE2b-256 |
0979f887ec7a8bdbefb23d3e04fcb71fdc169f1ab52587e2b119ef256f349d4e
|
File details
Details for the file crosstray-0.1.1-py3-none-any.whl.
File metadata
- Download URL: crosstray-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71246a63bca4e5b0fad445b563bff14e5ccff56b26b9bf496a28f1b3458c4c84
|
|
| MD5 |
cf55f6dde5967d543a7ffa46737712c3
|
|
| BLAKE2b-256 |
bc16cacab56059ed7f7d148b877205c60c623e7a06660da580ecc24ef3b6415c
|