You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动