Benny H. Benny H. - 1 month ago 7
Python Question

Event when Queue has Items in different Threads / Python3

I check in a separate Thread if there are any Informations in the pySerial Buffer (Infinite Loop). If so, i wanted to print that Input in a gtk.TextView. But after checking Google: Doing GTK-Stuff inside Threads is a Killer, random Errors will appear and so on, thats also a Problem i dealed with. So: Only Operations with the GUI in the Main-Loop.

I decided to use a Queue to synchronize both Threads, putting Information inside a Queue is pretty simple, but how do i suppose to check in the Main-Loop if there are any entries in the Queue? Some Kind of Event would be nice which triggers if any new Informations are available.

Is there anything of that Kind? Maybe there is exist a Function to implement Custom Python Code in the GTK3+ main_loop?


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

Here is where GObject comes in, to, as it is put in this (slightly outdated) link :

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

When we replace gobject.threads_init() by GObject.threads_init() and gobject.idle_add by GObject.idle_add(), 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:

Example, counting an updated number of monkeys in your TextView:

enter image description here...enter image description here...enter image description here

#!/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()

        scrolledwindow = Gtk.ScrolledWindow()
        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")

        # 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
        # 3. Start the thread

    def counting_monkeys(self):
        # replace this with your thread to update the text
        n = 1
        while True:
            newtext = str(n)+" monkey" if n == 1 else str(n)+" monkeys"
            n += 1

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