python - 线程中的 wxPython 无法正常关闭
问题描述
我是 wxPython 的新手,所以我基本上只是复制了一些会显示托盘图标并使其成为线程的内容:
import wx
import wx.adv
from threading import Thread
TRAY_TOOLTIP = 'System Tray Demo'
TRAY_ICON = 'icon.png'
class Main(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
self.app = App()
self.app.MainLoop()
def create_menu_item(menu, label, func):
item = wx.MenuItem(menu, -1, label)
menu.Bind(wx.EVT_MENU, func, id=item.GetId())
menu.Append(item)
return item
class TaskBarIcon(wx.adv.TaskBarIcon):
def __init__(self, frame):
self.frame = frame
super(TaskBarIcon, self).__init__()
self.set_icon(TRAY_ICON)
self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.on_left_down)
def CreatePopupMenu(self):
menu = wx.Menu()
create_menu_item(menu, 'Exit', self.on_exit)
return menu
def set_icon(self, path):
icon = wx.Icon(wx.Bitmap(path))
self.SetIcon(icon, TRAY_TOOLTIP)
def on_left_down(self, event):
print('Tray icon was left-clicked.')
def on_exit(self, event):
wx.CallAfter(self.Destroy)
self.frame.Close()
class App(wx.App):
def __init__(self):
wx.App.__init__(self, False)
def OnInit(self):
frame = wx.Frame(None)
self.SetTopWindow(frame)
TaskBarIcon(frame)
return True
从我的主线程,这是一个运行时间很长的服务,我正在启动 GUI 线程,激活调度程序并检查它是否应该像这样运行:
gui = trayIcon.Main()
gui.start()
schedule.every(60).minutes.do(main)
while gui.is_alive():
schedule.run_pending()
time.sleep(1)
# if this is reached the gui thread has terminated and the program should shut down
sys.exit()
它应该是这样工作的:当单击托盘图标菜单中的退出项时,GUI 线程关闭,然后在主线程的 while 循环中不再检测到并调用 sys.exit()。不幸的是,wxPython 然后显示一个错误对话框,其中包含以下文本:
wxWidgets 调试警报
....\src\common\socket.cpp(767): assert "wxIsMainThread()" failed in wxSocketBase::IsInitialized(): unsafe to call from other threads [in thread 1284] 你想停止程序吗?您也可以选择 [取消] 来抑制进一步的警告。
如何正确关闭 GUI 或至少抑制此警告?之后程序按原样退出,尽管我怀疑抑制消息会留下某种内存泄漏。
提前致谢
紫杉醇
解决方案
基本上看起来你已经把它倒过来了。主线程应该始终是 wxPython 线程。MainLoop 不应在线程内调用。相反,您应该让 wxPython 控制并在其中运行您长时间运行的线程。
然后当你长时间运行的任务完成后,你可以使用线程安全的方法,比如wx.CallAfter
告诉 wxPython 是时候退出了。由于 wxPython 是可控的,它可以正确地关闭自己。
以下是一些可能对您有所帮助的文章:
推荐阅读
- algorithm - What is the best approach for computing logarithm of an integer x base 2 approximated to the greatest integer less than or equal to it?
- java - 实现 Java FXML MVC 的建议
- git - Neovim 插件 Fugitive 没有使用 ssh 密钥代理,所以我不能 Gpush/Git 推送
- rspec - 在执行 Rake 任务时定义环境变量作为 RSpec 规范的一部分
- javascript - 有没有办法将多个(和不同的)参数从闪电网络组件(LWC)中的 JS 传递给 Apex 控制器类?
- c++ - 即使只有主函数,在主函数外部声明变量也会改变输出
- angular - 设置展开面板展开,同时也显示动画
- java - 是否存在提供任意深度嵌套以转换为 JSON 对象的 Java 类?
- go - 如何将记录器中间件输出数据传递到 golang 中的 mysql 表中?
- php - 如何在两个日期之间循环月份和年份