Rik Poggi
Rik Poggi

Reputation: 29302

Gtk+ 3 - Issues writing and autoscrolling in a TextView

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

Answers (2)

Marco Biscaro
Marco Biscaro

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

jcollado
jcollado

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

Related Questions