Gtk 在添加和删除列表框行时崩溃
Gtk crashes on adding and removing listboxrows
我想创建一个需要不断更新 ListBox
的 Gtk 程序,即添加和删除行。我正在尝试这种方法。它可能更干净,但这里它的长度足以解释问题。
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from time import sleep
from threading import Thread
def add_widgets(listbox):
# add 5 rows
for _ in range(5):
for _ in range(5):
add_row(listbox)
window.show_all() # make the changes visible
sleep(1) # to make the change stay
# remove all the rows
for row in listbox.get_children():
listbox.remove(row)
window.show_all()
sleep(1)
# all the addition and removal done
print('finished')
def add_row(listbox):
listboxrow = Gtk.ListBoxRow()
label = Gtk.Label()
label.set_text("Hey There")
listboxrow.add(label)
listbox.add(listboxrow)
window = Gtk.Window()
window.connect('destroy', Gtk.main_quit)
listbox = Gtk.ListBox()
window.add(listbox)
window.show_all()
# Thread to add and remove rows
update_thread = Thread(target=add_widgets, args=(listbox, ))
update_thread.start()
Gtk.main()
此代码在大约 50% 的时间内运行良好。对于其余的,它给了我 3 种类型的错误,所有错误都是随机的。
- 在
add_widgets
中父循环进行了 2 或 3 次迭代后的好旧 SegFault
- 以下:
**
Gtk:ERROR:../gtk/gtk/gtkcssnode.c:319:lookup_in_global_parent_cache: assertion failed: (node->cache == NULL)
Bail out! Gtk:ERROR:../gtk/gtk/gtkcssnode.c:319:lookup_in_global_parent_cache: assertion failed: (node->cache == NULL)
Aborted
- 最后一个不会使程序崩溃,但会添加随机行数。即它添加 3(随机)行而不是 5,如指定的或可能根本没有行。
我尝试在适当的地方添加更多的睡眠语句,因为最初,我想,这可能是因为更新小部件时 windows 没有准备好。
我想知道为什么会这样,我该如何解决。
编辑:这可能与 UI 和线程同步有关,因为它(崩溃)在与 [=39 交互时更频繁地发生=].例如,当你拖动它时,它更有可能崩溃。
您不得从其他线程调用 GTK+ 代码。所有交互都必须在主线程中完成。这记录在 https://developer.gnome.org/gdk3/stable/gdk3-Threads.html.
中
如果您想对小部件进行一些“后台”更新,您可以使用 g_idle_add()
(https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-idle-add), g_timeout_add()
(https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add) 等函数和其他相关函数来模拟。
我想创建一个需要不断更新 ListBox
的 Gtk 程序,即添加和删除行。我正在尝试这种方法。它可能更干净,但这里它的长度足以解释问题。
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from time import sleep
from threading import Thread
def add_widgets(listbox):
# add 5 rows
for _ in range(5):
for _ in range(5):
add_row(listbox)
window.show_all() # make the changes visible
sleep(1) # to make the change stay
# remove all the rows
for row in listbox.get_children():
listbox.remove(row)
window.show_all()
sleep(1)
# all the addition and removal done
print('finished')
def add_row(listbox):
listboxrow = Gtk.ListBoxRow()
label = Gtk.Label()
label.set_text("Hey There")
listboxrow.add(label)
listbox.add(listboxrow)
window = Gtk.Window()
window.connect('destroy', Gtk.main_quit)
listbox = Gtk.ListBox()
window.add(listbox)
window.show_all()
# Thread to add and remove rows
update_thread = Thread(target=add_widgets, args=(listbox, ))
update_thread.start()
Gtk.main()
此代码在大约 50% 的时间内运行良好。对于其余的,它给了我 3 种类型的错误,所有错误都是随机的。
- 在
add_widgets
中父循环进行了 2 或 3 次迭代后的好旧 - 以下:
SegFault
**
Gtk:ERROR:../gtk/gtk/gtkcssnode.c:319:lookup_in_global_parent_cache: assertion failed: (node->cache == NULL)
Bail out! Gtk:ERROR:../gtk/gtk/gtkcssnode.c:319:lookup_in_global_parent_cache: assertion failed: (node->cache == NULL)
Aborted
- 最后一个不会使程序崩溃,但会添加随机行数。即它添加 3(随机)行而不是 5,如指定的或可能根本没有行。
我尝试在适当的地方添加更多的睡眠语句,因为最初,我想,这可能是因为更新小部件时 windows 没有准备好。
我想知道为什么会这样,我该如何解决。
编辑:这可能与 UI 和线程同步有关,因为它(崩溃)在与 [=39 交互时更频繁地发生=].例如,当你拖动它时,它更有可能崩溃。
您不得从其他线程调用 GTK+ 代码。所有交互都必须在主线程中完成。这记录在 https://developer.gnome.org/gdk3/stable/gdk3-Threads.html.
中如果您想对小部件进行一些“后台”更新,您可以使用 g_idle_add()
(https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-idle-add), g_timeout_add()
(https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add) 等函数和其他相关函数来模拟。