【问题标题】:How to destroy the icon tray when the program ends程序结束时如何销毁图标托盘
【发布时间】:2019-12-09 04:33:47
【问题描述】:

我的 .py 程序启动时会调用一个类,它会在 Windows 任务栏中创建一个图标托盘。其中有选项quit,它映射到我的类中的函数kill_icon_tray,它应该终止图标然后完成我的程序。

这是类(有些方法因为不需要而被省略):

from infi.systray import SysTrayIcon

class Tray_icon_controller:

    def __init__(self):
        self.menu_options = (("Open Chat Monitor", None, self.open_chat),)
        self.systray = SysTrayIcon("chat.ico", "Engineer Reminder", self.menu_options, on_quit=self.kill_icon_tray);

    def init_icon_tray(self):
        self.systray.start();

    def kill_icon_tray(self, systray):
        self.systray.shutdown()

但是,每当我在图标托盘中单击 quit 时,都会返回以下异常:

$ py engineer_reminder.py
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 237, in 'calling callback function'
  File "C:\Users\i866336\AppData\Local\Programs\Python\Python38-32\lib\site-packages\infi\systray\traybar.py", line 79, in WndProc
    self._message_dict[msg](hwnd, msg, wparam.value, lparam.value)
  File "C:\Users\i866336\AppData\Local\Programs\Python\Python38-32\lib\site-packages\infi\systray\traybar.py", line 195, in _destroy
    self._on_quit(self)
  File "C:\Users\i866336\Documents\GitHub\chat_reminder\cl_tray_icon_controller.py", line 17, in kill_icon_tray
    self.systray.shutdown()
  File "C:\Users\i866336\AppData\Local\Programs\Python\Python38-32\lib\site-packages\infi\systray\traybar.py", line 123, in shutdown
    self._message_loop_thread.join()
  File "C:\Users\i866336\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 1008, in join
    raise RuntimeError("cannot join current thread")
RuntimeError: cannot join current thread

我尝试将 kill_icon_tray 方法修改为此,但它抛出了相同的异常:

    def kill_icon_tray(self, systray):
        self.systray.shutdown()

根据infi.systraydocumentation,我做得对:

要在程序结束时销毁图标,请调用systray.shutdown()

所以我不确定我在这里缺少什么......有人可以帮忙吗?谢谢!

【问题讨论】:

  • 它失败是因为在你的代码运行关闭时有一些线程你不能退出或加入。您应该将sys.exit(0) 写入您的线程函数机器人成功和异常以释放挂起的线程。
  • 问题是线程是由infi.systray api创建的,这意味着我不应该真正修改那里的任何东西..问题应该是我当前的实现,所以我应该在哪里使用这个@ 987654333@?

标签: python systray


【解决方案1】:

遇到与您相同的问题,您本可以找到解决方案,但对于遇到相同问题的其他人。

为我解决的问题是将 systray.shutdown() 更改为 SysTrayIcon.shutdown

    def kill_icon_tray(systray):
    SysTrayIcon.shutdown

希望对你有帮助

【讨论】:

    【解决方案2】:

    如果其他人遇到此问题,修补 SysTrayIcon.shutdown 方法是为我解决此问题的方法。

    from infi.systray import SysTrayIcon
    from infi.systray.traybar import PostMessage, WM_CLOSE
    
    
    # Remove the thread.join from the SysTrayIcon.shutdown function
    def custom_shutdown(self):
        if not self._hwnd:
            return      # not started
        PostMessage(self._hwnd, WM_CLOSE, 0, 0)
        #self._message_loop_thread.join()
    
    # Overwrite shutdown function
    SysTrayIcon.shutdown = custom_shutdown
    
    # Use it as normal
    sys_tray.shutdown()
    

    我不确定为什么会出现这个问题。在我的情况下,我有在 SysTrayIcon 对象的生命周期内创建和完成的守护进程,但在创建它们之前我可以 SysTrayIcon._message_loop_function.join() 成功到 MainThread,但之后我不能......

    无论如何,单独调用PostMessage(self._hwnd, WM_CLOSE, 0, 0) 似乎也可以。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      • 2015-09-29
      • 2016-12-24
      • 2019-05-02
      • 1970-01-01
      相关资源
      最近更新 更多