本文目录导读:

我来推荐几个实现系统托盘的Python方案。
使用 pystray(推荐)
import pystray
from pystray import MenuItem as item
from PIL import Image, ImageDraw
def create_image():
"""创建一个简单的图标"""
# 创建一个 64x64 的图像
image = Image.new('RGBA', (64, 64), (255, 255, 255, 0))
draw = ImageDraw.Draw(image)
# 画一个蓝色圆形
draw.ellipse([8, 8, 56, 56], fill='blue')
# 画一个白色字母 "P"
draw.text((20, 15), "P", fill='white', font=None)
return image
def on_quit(icon, item):
"""退出程序"""
icon.stop()
def on_show(icon, item):
"""显示信息"""
print("系统托盘示例运行中...")
def on_settings(icon, item):
"""设置菜单"""
print("打开设置...")
# 创建系统托盘图标
icon = pystray.Icon(
"test_icon",
create_image(),
"系统托盘示例",
menu=pystray.Menu(
item("显示信息", on_show),
item("设置", on_settings),
item("退出", on_quit)
)
)
# 运行系统托盘
if __name__ == "__main__":
print("系统托盘已启动")
icon.run()
使用 Infi.systray(跨平台)
from infi.systray import SysTrayIcon
import os
def on_quit_callback(systray):
"""退出回调"""
print("程序退出")
def on_show_info(systray):
"""显示信息"""
print("系统托盘正在运行")
def on_open_folder(systray):
"""打开文件夹"""
os.startfile('.') # Windows
# os.system('open .') # macOS
# os.system('xdg-open .') # Linux
# 设置菜单项
menu_options = (
("显示信息", None, on_show_info),
("打开文件夹", None, on_open_folder),
)
# 创建系统托盘
systray = SysTrayIcon(
"icon.ico", # 图标文件路径
"系统托盘示例",
menu_options,
on_quit_callback
)
# 启动
if __name__ == "__main__":
systray.start()
使用 PyQt5 实现
import sys
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMenu, QAction
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QTimer
class SystemTrayDemo:
def __init__(self):
self.app = QApplication(sys.argv)
# 设置应用图标
self.app.setWindowIcon(QIcon.fromTheme("applications-system"))
# 创建系统托盘
self.tray_icon = QSystemTrayIcon()
self.tray_icon.setIcon(QIcon.fromTheme("applications-system"))
self.tray_icon.setToolTip("系统托盘示例")
# 创建右键菜单
self.create_menu()
# 连接信号
self.tray_icon.activated.connect(self.on_activated)
# 显示系统托盘
self.tray_icon.show()
# 定时器示例
self.timer = QTimer()
self.timer.timeout.connect(self.update_status)
self.timer.start(5000) # 每5秒更新一次
def create_menu(self):
"""创建右键菜单"""
menu = QMenu()
# 显示信息
show_action = QAction("显示信息", self.tray_icon)
show_action.triggered.connect(self.show_info)
menu.addAction(show_action)
# 设置
settings_action = QAction("设置", self.tray_icon)
settings_action.triggered.connect(self.open_settings)
menu.addAction(settings_action)
menu.addSeparator()
# 退出
quit_action = QAction("退出", self.tray_icon)
quit_action.triggered.connect(self.quit_app)
menu.addAction(quit_action)
self.tray_icon.setContextMenu(menu)
def on_activated(self, reason):
"""系统托盘被激活时的回调"""
if reason == QSystemTrayIcon.DoubleClick:
self.show_info()
def show_info(self):
"""显示信息"""
self.tray_icon.showMessage(
"系统托盘",
"这是一个系统托盘示例",
QSystemTrayIcon.Information,
3000 # 显示3秒
)
def open_settings(self):
"""打开设置"""
print("打开设置界面")
def update_status(self):
"""定时更新状态"""
self.tray_icon.setToolTip(f"系统托盘 - {QtCore.QTime.currentTime().toString()}")
def quit_app(self):
"""退出应用"""
QApplication.quit()
def run(self):
"""运行应用"""
sys.exit(self.app.exec_())
# 运行
if __name__ == "__main__":
demo = SystemTrayDemo()
demo.run()
使用 wxPython
import wx
class TaskBarIcon(wx.TaskBarIcon):
def __init__(self, frame):
super().__init__()
self.frame = frame
# 设置图标
icon = wx.Icon()
icon.LoadFile("icon.ico", wx.BITMAP_TYPE_ICO)
self.SetIcon(icon, "系统托盘示例")
# 绑定事件
self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.on_double_click)
self.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.on_right_click)
def CreatePopupMenu(self):
"""创建右键菜单"""
menu = wx.Menu()
# 显示窗口
show_item = menu.Append(wx.ID_ANY, "显示窗口")
self.Bind(wx.EVT_MENU, self.on_show, show_item)
# 设置
settings_item = menu.Append(wx.ID_ANY, "设置")
self.Bind(wx.EVT_MENU, self.on_settings, settings_item)
menu.AppendSeparator()
# 退出
quit_item = menu.Append(wx.ID_ANY, "退出")
self.Bind(wx.EVT_MENU, self.on_quit, quit_item)
return menu
def on_double_click(self, event):
"""双击事件"""
self.frame.Show()
self.frame.Raise()
def on_right_click(self, event):
"""右键事件"""
self.PopupMenu(self.CreatePopupMenu())
def on_show(self, event):
"""显示窗口"""
self.frame.Show()
self.frame.Raise()
def on_settings(self, event):
"""打开设置"""
print("打开设置")
def on_quit(self, event):
"""退出程序"""
self.frame.Close()
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="系统托盘示例")
# 创建系统托盘
self.tray_icon = TaskBarIcon(self)
# 创建主界面
panel = wx.Panel(self)
text = wx.StaticText(panel, label="双击系统托盘图标显示窗口", pos=(50, 50))
# 最小化到系统托盘
self.Bind(wx.EVT_ICONIZE, self.on_minimize)
self.Show()
def on_minimize(self, event):
"""最小化时隐藏窗口"""
self.Hide()
# 运行
if __name__ == "__main__":
app = wx.App()
frame = MyFrame()
app.MainLoop()
安装依赖
根据选择的方案安装相应库:
# 方案一 pip install pystray pillow # 方案二 pip install infi.systray # 方案三 pip install PyQt5 # 方案四 pip install wxPython
完整示例:带有后台线程的系统托盘
import pystray
from pystray import MenuItem as item
from PIL import Image, ImageDraw
import threading
import time
import random
class SystemTrayApp:
def __init__(self):
self.running = True
self.counter = 0
# 创建图标
self.icon = pystray.Icon(
"demo_icon",
self.create_image(),
"系统托盘演示",
self.create_menu()
)
def create_image(self):
"""创建动态图标"""
image = Image.new('RGBA', (64, 64), (255, 255, 255, 0))
draw = ImageDraw.Draw(image)
# 随机颜色
r, g, b = random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
draw.ellipse([8, 8, 56, 56], fill=(r, g, b))
draw.text((20, 15), str(self.counter), fill='white')
return image
def create_menu(self):
"""创建菜单"""
return pystray.Menu(
item("状态", self.show_status),
item("更新图标", self.update_icon),
item("重置计数", self.reset_counter),
item("退出", self.quit_app)
)
def show_status(self, icon, item):
"""显示状态"""
icon.notify(f"计数器: {self.counter}", "系统托盘状态")
def update_icon(self, icon, item):
"""更新图标"""
icon.icon = self.create_image()
def reset_counter(self, icon, item):
"""重置计数器"""
self.counter = 0
self.update_icon(icon, item)
def quit_app(self, icon, item):
"""退出应用"""
self.running = False
icon.stop()
def background_task(self):
"""后台任务"""
while self.running:
time.sleep(2)
self.counter += 1
print(f"计数器: {self.counter}")
def run(self):
"""运行应用"""
# 启动后台线程
bg_thread = threading.Thread(target=self.background_task)
bg_thread.daemon = True
bg_thread.start()
# 运行系统托盘
self.icon.run()
# 运行应用
if __name__ == "__main__":
app = SystemTrayApp()
app.run()
注意事项
- 图标文件:确保图标文件存在,或使用 PIL/Pillow 动态生成
- 平台兼容性:pystray 支持 Windows、macOS 和 Linux
- 线程安全:在后台线程中更新图标时要注意线程安全
- 资源释放:程序退出时正确清理资源
这些方案各有特点:
- pystray:简单易用,功能完整
- Infi.systray:轻量级,适合简单的系统托盘
- PyQt5/wxPython:适合需要复杂 GUI 的应用
选择哪种方案取决于你的具体需求和项目规模。