首页 > 解决方案 > 为什么我在使用 pystray 时无法关闭?

问题描述

我使用 tkinter 编写了一个程序,当主窗口关闭时,它应该被最小化到系统托盘。但是,当我尝试退出程序时,单击托盘中的“关闭”会触发以下功能:

def quit_window(icon, item):
    icon.stop() # Удаление иконки из трея
    sys.exit(0) # Завершение программы

但它不起作用并引发以下异常:

An error occurred when calling message handler
Traceback (most recent call last):
  File "C:\Users\a-par\mini_library_2020\env\lib\site-packages\pystray\_win32.py", line 386, in _dispatcher
    return int(icon._message_handlers.get(
  File "C:\Users\a-par\mini_library_2020\env\lib\site-packages\pystray\_win32.py", line 207, in _on_notify 
    descriptors[index - 1](self)
  File "C:\Users\a-par\mini_library_2020\env\lib\site-packages\pystray\_base.py", line 267, in inner
    callback(self)
  File "C:\Users\a-par\mini_library_2020\env\lib\site-packages\pystray\_base.py", line 368, in __call__
    return self._action(icon, self)
  File "c:/Users/a-par/mini_library_2020/LC.pyw", line 2976, in quit_window
    sys.exit(0)
SystemExit: 0

程序中还有一个 VK bot,它应该在程序最小化时工作(这是实际最小化到托盘的原因)。该机器人在不同于 GUI 线程中工作。我试图完全删除该机器人,但没有任何帮助。也许问题是线程,但我不这么认为......

最小可重现的非工作代码:

import pystray
import sys
import time
from PIL import Image
from pystray import Menu, MenuItem


def exit_action(icon):
    sys.exit(0)


def setup(icon):
    icon.visible = True
    
    i = 0
    while icon.visible:
        # Some payload code
        print(i)
        i += 1
        
        time.sleep(5)


def init_icon():
    icon = pystray.Icon('mon')
    icon.menu = Menu(
        MenuItem('Exit', lambda : exit_action(icon)),
    )
    icon.icon = Image.open('C:/Users/a-par/mini_library_2020/logo.ico')
    icon.title = 'tooltip'

    icon.run(setup)

init_icon()

视频

标签: pythonpython-3.xmultithreadingtkinterpystray

解决方案


sys.exit()不会工作,因为它不是从主线程或其他东西执行的。您需要使用icon.stop()来关闭 pystray 的事件循环,从而停止整个程序。


推荐阅读