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.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:
#!/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" self.textbuffer.set_text(newtext) 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()