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

如何实现PySimpleGUI的SystemTray.notify非阻塞/异步调用?

解决方案

现有实现的核心问题

  • 仅存储单个弹窗实例,新通知生成时会覆盖旧实例引用,触发Ok事件时仅能关闭最新弹窗,旧弹窗无法被正常管理
  • 事件循环中重复调用tray.read()和sg.read_all_windows(),两处timeout配置会导致事件响应出现延迟甚至阻塞
  • create_popup依赖全局变量myresult,多通知场景下会出现内容错乱
  • 多通知未做位置偏移,新弹窗会完全覆盖旧弹窗

可行实现方案

不需要引入多线程,直接通过PySimpleGUI原生的多窗口事件管理机制就可以实现非阻塞的多通知驻留效果,修改后代码如下:

import PySimpleGUI as sg
import random

# 存储所有活跃的通知窗口
active_popups = []

def create_popup(title, content):
    dx, dy = sg.SYSTEM_TRAY_WIN_MARGINS
    screen_res_x, screen_res_y = sg.Window.get_screen_size()
    layout = [
        [sg.Text(title, font=("微软雅黑", 10, "bold"))],
        [sg.Text(content, font=("微软雅黑", 9))],
        [sg.Button('Ok', size=(10, 1))]
    ]
    window = sg.Window(
        "通知", layout, 
        keep_on_top=True, no_titlebar=True, 
        grab_anywhere=True, finalize=True,
        alpha_channel=0.95  # 可调整透明度优化视觉效果
    )
    width, height = window.size
    # 多通知自动向上偏移,避免重叠
    offset_y = len(active_popups) * (height + 10)
    window.move(screen_res_x - width - dx, screen_res_y - height - dy - offset_y)
    return window

# 初始化系统托盘
tray = sg.SystemTray(menu=['menu', ['Open', 'Exit']], filename='icon.ico') # 自行替换图标路径

def query():
    # 你的MySQL查询逻辑,这里仅做示例返回
    # 实际使用时替换为你的数据库查询代码,返回 (通知ID, 通知标题, 通知内容)
    return (random.randint(1, 1000), "通知标题测试", "通知内容测试")

last_notification_id = 0

while True:
    # 统一读取所有事件:托盘+所有通知窗口,非阻塞
    win, event, values = sg.read_all_windows(timeout=10000)
    
    # 处理退出逻辑
    if event in (sg.WINDOW_CLOSED, 'Exit'):
        break
    
    # 处理托盘菜单事件
    if win == tray:
        if event == 'Open':
            sg.popup('后续功能开发中')
    
    # 处理通知窗口的Ok按钮事件
    if event == 'Ok':
        win.close()
        if win in active_popups:
            active_popups.remove(win)
    
    # 轮询查询新通知
    current_notification = query()
    current_notification_id = current_notification[0]
    if current_notification_id > last_notification_id:
        # 生成新通知窗口加入活跃列表
        new_popup = create_popup(current_notification[1], current_notification[2])
        active_popups.append(new_popup)
        last_notification_id = current_notification_id

# 退出时关闭所有残留窗口
for popup in active_popups:
    popup.close()
tray.close()

关键改动说明

  • 用active_popups列表统一管理所有驻留的通知窗口,支持同时存在多条通知
  • 统一使用sg.read_all_windows()处理所有事件,全程非阻塞,不会卡住新通知的查询和推送
  • 新通知生成时自动向上偏移位置,避免重叠覆盖,视觉上更清晰
  • 所有窗口操作都在主线程事件循环中执行,避免跨线程操作GUI导致的异常问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:45:03