重新打开 window 抛出 Gtk-CRITICAL **:gtk_widget_get_window:断言 'GTK_IS_WIDGET (widget)' 失败
Reopen window throws Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed
我有简单的 python3 + gtk3 代码,它连接到 dbus 并监听所有事件。当用户单击托盘中的图标时,他必须看到 window 以及所有显示的早期事件。代码(我不知道问题在哪里,代码大小> 100行):https://github.com/rakshazi/notify-feed/blob/master/main.py
如何重现:
- 运行
python main.py
L117
- 点击托盘中的应用程序图标 - 将被打开 window,如果 运行 之后显示任何通知,它可以是空的或带有一些项目。 L83
- 关闭window。 L93
- 重试第 2 步,你会看到空的 window(在所有情况下都没有任何元素,是的,这是错误,但对这个问题无关紧要)
点击window正文,应用程序将崩溃:
(gui.py:4882): Gtk-CRITICAL **: gtk_widget_get_window: 断言 'GTK_IS_WIDGET (widget)' 失败
[1]
4882 分段错误(核心已转储)python gui.py
第一个 windowOpen 事件和第二个 windowOpen 事件 self.window
对象是 <__main__.Window object at 0x7f98b1dcd7e0 (__main__+Window at 0x1502260)>
gdb 结果:
(main.py:17310): Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed
Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffea5cd0b8 in gtk_widget_translate_coordinates () from /usr/lib/libgtk-3.so.0
请向我解释如何调试和修复此问题。
PS:我是Python的新手,这就是为什么这个问题可能很愚蠢。
第 1 课:永远不要假设错误无关
第 2 课:GTK 事件令人困惑。
您收到此错误的原因是因为 window 实际上在您在第 3 步中关闭它时被删除,因此 window 中的所有小部件都变成孤立的(它们没有父级)并且因此被清洁。在第 4 步中第二次打开 window 时,window 仅包含对已删除小部件的引用,导致您的分段错误。
解决方案非常简单,只需将 return True
添加到 closeWindow
这将使 GTK 知道事件已被处理并且它不应执行关闭 window 的默认操作(你已经隐藏了)。
另一个优雅的解决方案可能是使用 hide_on_delete
函数。例如在 Rust 中(很容易重写为 Python):
my_window.connect_delete_event(move |_win,_| {
_win.hide_on_delete()
});
我有简单的 python3 + gtk3 代码,它连接到 dbus 并监听所有事件。当用户单击托盘中的图标时,他必须看到 window 以及所有显示的早期事件。代码(我不知道问题在哪里,代码大小> 100行):https://github.com/rakshazi/notify-feed/blob/master/main.py
如何重现:
- 运行
python main.py
L117 - 点击托盘中的应用程序图标 - 将被打开 window,如果 运行 之后显示任何通知,它可以是空的或带有一些项目。 L83
- 关闭window。 L93
- 重试第 2 步,你会看到空的 window(在所有情况下都没有任何元素,是的,这是错误,但对这个问题无关紧要)
点击window正文,应用程序将崩溃:
(gui.py:4882): Gtk-CRITICAL **: gtk_widget_get_window: 断言 'GTK_IS_WIDGET (widget)' 失败
[1]
4882 分段错误(核心已转储)python gui.py
第一个 windowOpen 事件和第二个 windowOpen 事件 self.window
对象是 <__main__.Window object at 0x7f98b1dcd7e0 (__main__+Window at 0x1502260)>
gdb 结果:
(main.py:17310): Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed
Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffea5cd0b8 in gtk_widget_translate_coordinates () from /usr/lib/libgtk-3.so.0
请向我解释如何调试和修复此问题。
PS:我是Python的新手,这就是为什么这个问题可能很愚蠢。
第 1 课:永远不要假设错误无关
第 2 课:GTK 事件令人困惑。
您收到此错误的原因是因为 window 实际上在您在第 3 步中关闭它时被删除,因此 window 中的所有小部件都变成孤立的(它们没有父级)并且因此被清洁。在第 4 步中第二次打开 window 时,window 仅包含对已删除小部件的引用,导致您的分段错误。
解决方案非常简单,只需将 return True
添加到 closeWindow
这将使 GTK 知道事件已被处理并且它不应执行关闭 window 的默认操作(你已经隐藏了)。
另一个优雅的解决方案可能是使用 hide_on_delete
函数。例如在 Rust 中(很容易重写为 Python):
my_window.connect_delete_event(move |_win,_| {
_win.hide_on_delete()
});