Ridiculously Uncomplicated Windows Python Systray apps.
ruwps
exposes Winapi functions as Python classes and functions which greatly simplifies the process of creating a system tray application, i.e. an application that is supposed to run in the background and only has a minimal GUI based on menus and simple dialogs. It's a complement to rumps
, sharing (mostly) the same API, which allows the fast creation of Windows/macOS cross-platform system tray/statusbar applications based on the same code.
Here a minimal example app:
import ruwps
class AwesomeApp(ruwps.App):
@ruwps.clicked("Preferences")
def prefs(self, _):
rumps.alert("jk! no preferences available!")
@ruwps.clicked("Silly button")
def onoff(self, sender):
sender.state = not sender.state
@ruwps.clicked("Say hi")
def sayhi(self, _):
ruwps.notification("Awesome title", "amazing subtitle", "hi!!1")
if __name__ == "__main__":
AwesomeApp("Awesome App").run()
And here the same app as above, but written in a way so that it runs both in Windows and macOS:
import sys
IS_MAC = sys.platform == 'darwin'
IS_WIN = sys.platform == 'win32'
if IS_MAC:
import rumps as rups
elif IS_WIN:
import ruwps as rups
else:
print('Linux not supported!') # We really also need rulps! ;-)
sys.exit(1)
class AwesomeApp(rups.App):
@rups.clicked("Preferences")
def prefs(self, _):
rups.alert("jk! no preferences available!")
@rups.clicked("Silly button")
def onoff(self, sender):
sender.state = not sender.state
@rups.clicked("Say hi")
def sayhi(self, _):
rups.notification("Awesome title", "amazing subtitle", "hi!!1")
if __name__ == "__main__":
AwesomeApp("Awesome App").run()
The resulting app running in Windows 11:
The resulting app, based on rumps
, running in macOS 13:
git clone https://github.com/59de44955ebd/ruwps.git
pip install -e ruwps
The examples folder contains 9 example Python scripts, which were all directly copied from rumps
and then made cross-platform.
The demo_socks_manager folder contains a (still simple) actual cross-platform application that allows to start/stop/manage SOCKS5 proxies/SSH tunnels both in Windows and macOS.
Running batch script make_dist_windows.cmd in the examples folder will create a standalone .exe for the minimal "AwsomeApp" demo shown above. If you have 7-Zip installed at the default location, the script will also create a file called "AwesomeApp-x64-portable.7z". If you have NSIS installed at the default location, the script will also create a file called "AwesomeApp-x64-setup.exe".
Running make_dist_macos.command in macOS will create a standalone app for macOS as well as a compressed .dmg image called "AwesomeApp.dmg", based on the same Python code and rumps
instead of ruwps
.
Running scripts make_dist_windows.cmd and make_dist_macos.command in the demo_socks_manager folder does the same thing for the SocksManager demo application.
The ruwps
API is (almost) the same as for rumps
, so you can refer to the rumps documentation.
But of course there are some differences, since the underlying system APIs differ. Here some of those differences:
- The app's systray icon is loaded from an .ico file (instead of a .icns file in macOS). If you don't specify a custom icon, at dev time some arbitrary b&w default icon (see screenshots) is used, while in a frozen application the application's main icon (that was passed to pyinstaller) is used instead.
- The Winapi doesn't support automatic icon conversion based on the user's current light/dark mode, therefor the optional
template
argument of the App's constructor works differently inruwps
, if it is specified and set to True, theicon
argument has to be a tuple/list of two icon files, and the first is then used in light and the second in dark mode. - Menu icons (optional) are loaded from .bmp files (instead of .png or .jpg files in macOS). The optional
dimensions
argument is ignored. - In macOS the app can either show an icon or text in the statusbar, while in the Windows system tray it's always an icon. The
title
property of the App class instead only determines the icon's tooltip. - If debug mode is activated and the app is frozen (i.e. there is no console to print to), debug infos are printed to the Windows debug console and can be monitored using Sysinternal's DebugView.