You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用pystray根据ping值动态更改系统托盘图标?

解决pystray系统托盘图标无法根据ping结果动态更新的问题

问题根源

你的代码每次循环都新建pystray.Icon实例并调用icon.run(),但run()是阻塞式的事件循环方法,第一次执行后程序就会停在这个方法里,无法进入下一次循环,自然没法更新图标。

修正方案

正确思路是只初始化一次托盘图标,在单独线程中执行ping检测和图标更新逻辑,通过修改已有图标的image属性实现动态切换:

import pystray
import ping3
import threading
import time
from PIL import Image

# 提前加载所有图标(替换为你的图标文件路径)
white_icon = Image.open("white.png")
green_icon = Image.open("green.png")
yellow_icon = Image.open("yellow.png")
orange_icon = Image.open("orange.png")
red_icon = Image.open("red.png")

def update_tray_icon(icon):
    while True:
        p_out = ping3.ping("google.com", unit="ms")
        # 处理ping返回None的情况(网络不通时会返回空值)
        if p_out is None:
            current_icon = red_icon
        elif p_out == 0:
            current_icon = white_icon
        elif p_out >= 999:
            current_icon = red_icon
        else:
            print(f'\n{p_out:4.0f}', end='')
            if p_out <= 50:
                current_icon = green_icon
            elif p_out <= 60:
                current_icon = yellow_icon
            elif p_out < 100:
                current_icon = orange_icon
            else:
                current_icon = red_icon
        
        # 更新图标并通知系统刷新
        icon.image = current_icon
        icon.update()
        # 控制检测间隔,按需调整
        time.sleep(2)

# 初始化托盘图标,默认用绿色图标
icon = pystray.Icon("ping_monitor", green_icon)

# 启动ping检测的守护线程,不阻塞主事件循环
threading.Thread(target=update_tray_icon, args=(icon,), daemon=True).start()

# 启动托盘图标事件循环
icon.run()

关键细节

  • 用PIL提前加载所有图标资源,避免每次切换时重复读取文件
  • 守护线程负责ping检测和图标更新,不影响pystray的主事件循环
  • 修改icon.image后调用icon.update(),强制系统刷新托盘显示
  • 增加time.sleep()控制检测频率,避免过度占用资源
  • 额外处理了ping返回None的异常场景(比如网络断开)

内容的提问来源于stack exchange,提问作者Douglas Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:10:37