How can I update a Gtk.TextView from events from a different thread?
<p>In a separate thread, I check for information in the pySerial Buffer (Infinite Loop). If new information is available, I'd like to show that Input in a <code>Gtk.TextView</code>. After Googling on the subject it turns out doing Gtk -Stuff inside threads is a killer. Random errors will appear and so on, which was also a problem I ran into.</p>

<p>I decided to use a queue to synchronize the thread with the GUI. Putting information into a queue is pretty simple, but how do I suppose to check in the mainloop if there are any entries in the queue? </p>

<p>Some kind of event would be nice, which triggers if any new information is available.</p>

<p>Is there anything of that kind? Maybe a function exists to implement custom python code into the GTK3+ mainloop?</p>

<p>To successfully periodically update the GUI from events in a thread, we cannot simply use <code>threading</code> to start a second process. Like you mention, it will lead to conflicts.</p>

<p>Here is where <code>GObject</code> comes in, to, as it is put in <a href="http://faq.pygtk.org/index.py?req=edit&amp;file=faq20.006.htp" rel="nofollow">this (slightly outdated) link</a> :</p>

<blockquote>
  <p>call gobject.threads_init() at applicaiton initialization. Then you launch your threads normally, but make sure the threads never do any GUI tasks directly. Instead, you use gobject.idle_add to schedule GUI task to executed in the main thread</p>
</blockquote>

<p>When we replace <code>gobject.threads_init()</code> by <code>GObject.threads_init()</code> and <code>gobject.idle_add</code> by <code>GObject.idle_add()</code>, we pretty much have the updated version of how to run threads in a Gtk application. A simplified example, showing an increasing number of Monkeys in your textfield. See the comments in the code:</p>

<h3>Example, counting an updated number of monkeys in your TextView:</h3>

<p><a href="http://i.stack.imgur.com/Urg2i.png" rel="nofollow"><img src="http://i.stack.imgur.com/Urg2i.png" alt="enter image description here"></a>...<a href="http://i.stack.imgur.com/9MLbC.png" rel="nofollow"><img src="http://i.stack.imgur.com/9MLbC.png" alt="enter image description here"></a>...<a href="http://i.stack.imgur.com/3oxkx.png" rel="nofollow"><img src="http://i.stack.imgur.com/3oxkx.png" alt="enter image description here"></a></p>

<pre><code>#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
import time
from threading import Thread

class InterFace(Gtk.Window):

    def __init__(self):

        Gtk.Window.__init__(self, title="Test 123")

        maingrid = Gtk.Grid()
        maingrid.set_border_width(10)
        self.add(maingrid)

        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)
        scrolledwindow.set_min_content_height(50)
        scrolledwindow.set_min_content_width(150)
        maingrid.attach(scrolledwindow, 0,0,1,1)

        self.textfield = Gtk.TextView()
        self.textbuffer = self.textfield.get_buffer()
        self.textbuffer.set_text("Let's count monkeys")
        self.textfield.set_wrap_mode(Gtk.WrapMode.WORD)
        scrolledwindow.add(self.textfield)

        # 1. define the tread, updating your text
        self.update = Thread(target=self.counting_monkeys)
        # 2. Deamonize the thread to make it stop with the GUI
        self.update.setDaemon(True)
        # 3. Start the thread
        self.update.start()

    def counting_monkeys(self):
        # replace this with your thread to update the text
        n = 1
        while True:
            time.sleep(2)
            newtext = str(n)+" monkey" if n == 1 else str(n)+" monkeys"
            GObject.idle_add(
                self.textbuffer.set_text, newtext,
                priority=GObject.PRIORITY_DEFAULT
                )
            n += 1

def run_gui():
    window = InterFace()
    # 4. this is where we call GObject.threads_init()
    GObject.threads_init()
    window.show_all()
    Gtk.main()

run_gui()
</code></pre>

python user-interface queue gtk3 python-multithreading