Reputation: 135
I want to create a Gtk program that requires to continuously update a ListBox
, i.e. add and remove rows. I am trying this approach. It could be cleaner but here it is just long enough to explain the problem.
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()
This code runs fine like 50% of the time. For the rest, it gives me 3 types of errors, all of them randomly.
SegFault
after like 2 or 3 iteration of the parent loop in add_widgets
**
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
I've tried adding more sleep statements at appropriate places because initially, I thought, it could be because the windows are not ready when updating widgets.
I wanna know why its happening and how can I fix it.
EDIT: It's probably something to do with the UI and the thread synchronization because, it(the crash) happens more frequently when interacting with the window. For instance, when you are dragging it, it has more chances of crashing.
Upvotes: 1
Views: 609
Reputation: 1012
You must not call GTK+ code from other threads. All interactions must be done in the main thread. This is documented in https://developer.gnome.org/gdk3/stable/gdk3-Threads.html.
If you want to do some "background" updates of your widgets, you can simulate that with functions such as 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) and other related functions.
Upvotes: 3