Reputation: 29302
I have a Gtk.ScrolledWindow()
with inside a Gtk.TextView()
, (I'm using PyGObject introspection).
After I insert some text and autoscroll from another thread, calling several times in a row the method append_text
, I get a couple of warnings then the GUI crashes.
This is the troublesome part of my code:
class TextViewWindow(Gtk.Window):
[...]
def append_text(self, text):
self.textbuffer.insert(self.textbuffer.get_end_iter(), text)
self.scroll_to_end()
def scroll_to_end(self):
self.textbuffer.place_cursor(self.textbuffer.get_end_iter())
insert_mark = self.textbuffer.get_insert()
self.textview.scroll_to_mark(insert_mark , 0.0, True, 0.0, 1.0)
Does anyone know what I'm doing wrong?
--
Here are some of the errors that I got:
Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created. You must use marks, character numbers, or line numbers to preserve a position across buffer modifications. You can apply tags and insert marks without invalidating your iterators, but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset) will invalidate all outstanding iterators
Pango-CRITICAL **: pango_layout_index_to_pos: assertion `layout != NULL' failed
Gtk-WARNING **: gtktextview.c:4813: somehow some text lines were modified or scrolling occurred since the last validation of lines on the screen - may be a text widget bug.
Gtk:ERROR:gtktextview.c:4814:gtk_text_view_paint: code should not be reached
Upvotes: 4
Views: 2588
Reputation: 1268
To update Gtk widgets from other threads, you need to:
a. Call the following methods before you call Gtk.main()
GObject.threads_init()
Gdk.threads_init()
b. In your thread, surround the code that updates the Gtk widgets with:
Gdk.threads_enter()
# your code here
Gdk.threads_leave()
In your case, you'll probably need something like:
Gdk.threads_enter()
your_window.append_text('something')
your_window.scroll_to_end()
Gdk.threads_leave()
Upvotes: 3
Reputation: 40414
If you're using threads, as it seems from your comments, according to my experience, trying to update widgets in threads doesn't work well.
A workaround to this problem is schedule all the actions that update widgets using GLib.idle_add
so that the update happens in the main thread.
Upvotes: 1