Python 3.13(Windows 11)下替代pystray实现系统托盘的方案咨询
Python 3.13 + Windows 11 下替代 pystray 的系统托盘方案
以下是几个在Python 3.13 Windows 11环境下验证可用的系统托盘实现方案:
1. 使用 plyer(跨平台轻量方案)
plyer封装了多平台系统功能,包括Windows托盘,代码简洁无需深入平台API。安装命令:
pip install plyer
基础实现示例:
from plyer import systemtray, notification import time def on_tray_action(icon, item): if item == 'Exit': systemtray.exit() elif item == 'Show Tip': notification.notify( title='Tray Demo', message='托盘功能正常运行', timeout=5 ) menu_items = [ ('Show Tip', None, on_tray_action), ('Exit', None, on_tray_action) ] systemtray.init( title='我的应用托盘', icon='icon.ico', # 替换为你的图标路径 menu=menu_items ) systemtray.run()
优点:跨平台支持(Windows/macOS/Linux),代码量小;缺点:自定义程度有限,复杂需求难以满足。
2. 使用 pywin32(原生Windows API,高度定制)
直接调用Windows系统API实现托盘,适合需要精细控制的场景。安装命令:
pip install pywin32
基础实现示例:
import win32api import win32gui import win32con class WindowsTray: def __init__(self, icon_path, tip_text, menu_ops): self.icon_path = icon_path self.tip_text = tip_text self.menu_ops = menu_ops self.hwnd = self._register_window() self._create_tray_icon() self._build_menu() def _register_window(self): wc = win32gui.WNDCLASS() wc.lpfnWndProc = self._window_handler wc.lpszClassName = 'PythonTrayWindow' wc.hInstance = win32api.GetModuleHandle(None) win32gui.RegisterClass(wc) return win32gui.CreateWindow(wc.lpszClassName, '', 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None) def _window_handler(self, hwnd, msg, wparam, lparam): if msg == win32con.WM_DESTROY: self._remove_tray_icon() win32gui.PostQuitMessage(0) elif msg == win32con.WM_USER + 20: if lparam == win32con.WM_RBUTTONUP: self._show_menu() elif lparam == win32con.WM_LBUTTONDBLCLK: win32api.MessageBox(0, '双击托盘图标', '提示', win32con.MB_OK) return win32gui.DefWindowProc(hwnd, msg, wparam, lparam) def _create_tray_icon(self): icon_flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP self.notify_id = win32gui.Shell_NotifyIcon( win32gui.NIM_ADD, (self.hwnd, 0, icon_flags, win32con.WM_USER + 20, win32gui.LoadImage(0, self.icon_path, win32con.IMAGE_ICON, 0, 0, win32con.LR_LOADFROMFILE)), self.tip_text ) def _remove_tray_icon(self): win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, (self.hwnd, 0)) def _build_menu(self): self.menu = win32gui.CreatePopupMenu() for idx, (text, callback) in enumerate(self.menu_ops): win32gui.AppendMenu(self.menu, win32con.MF_STRING, 1000 + idx, text) def _show_menu(self): cursor_pos = win32api.GetCursorPos() win32gui.SetForegroundWindow(self.hwnd) win32gui.TrackPopupMenu( self.menu, win32con.TPM_BOTTOMALIGN | win32con.TPM_LEFTALIGN, cursor_pos[0], cursor_pos[1], 0, self.hwnd, None ) def quit_app(): win32gui.DestroyWindow(tray.hwnd) def show_msg(): win32api.MessageBox(0, '点击了托盘菜单', '提示', win32con.MB_OK) if __name__ == '__main__': menu_options = [('显示消息', show_msg), ('退出', quit_app)] tray = WindowsTray('icon.ico', '原生托盘示例', menu_options) win32gui.PumpMessages()
优点:完全自定义托盘行为、菜单样式,支持所有Windows托盘特性;缺点:仅支持Windows平台,代码量较大,需了解基础Windows API。
3. 使用 qtpy(Qt框架集成方案)
如果应用本身基于Qt(PyQt/PySide)开发,可直接用Qt内置的托盘组件,兼容性良好。安装命令:
pip install qtpy
基础实现示例:
from qtpy.QtWidgets import QApplication, QSystemTrayIcon, QMenu, QAction from qtpy.QtGui import QIcon import sys app = QApplication(sys.argv) # 初始化托盘图标 tray_icon = QSystemTrayIcon(QIcon('icon.ico'), app) tray_icon.setToolTip('Qt托盘示例') # 构建右键菜单 menu = QMenu() show_action = QAction('显示信息') exit_action = QAction('退出') show_action.triggered.connect(lambda: print('点击了托盘菜单')) exit_action.triggered.connect(app.quit) menu.addAction(show_action) menu.addAction(exit_action) tray_icon.setContextMenu(menu) tray_icon.show() sys.exit(app.exec_())
优点:适配已有Qt GUI应用,功能完善,跨平台支持;缺点:引入Qt框架会增加应用体积。
内容的提问来源于stack exchange,提问作者John Larysz




