在一个单独的线程中,我检查 pySerial 缓冲区(无限循环)中的信息。如果有新信息可用,我想在 Gtk.TextView
中显示该输入。在对这个主题进行谷歌搜索后,发现在线程中执行 Gtk -Stuff 是一个 killer 。会出现随机错误等等,这也是我遇到的问题。
我决定使用队列来使线程与 GUI 同步。将信息放入队列非常简单,但是如果队列中有任何条目,我该如何检查主循环呢?
某种事件会很好,如果有任何新信息可用,它就会触发。
有这样的吗?也许存在将自定义 python 代码实现到 GTK3+ 主循环中的函数?
最佳答案
要通过线程中的事件成功地定期更新 GUI,我们不能简单地使用 threading
来启动第二个进程。正如您提到的,这会导致冲突。
这是 GObject
出现的地方,因为它被放在 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
当我们将 gobject.threads_init()
替换为 GObject.threads_init()
并将 gobject.idle_add
替换为 GObject.idle_add( )
,我们几乎已经有了关于如何在 Gtk 应用程序中运行线程的更新版本。一个简化的示例,在您的文本字段中显示越来越多的猴子。看代码中的注释:
例如,计算 TextView 中猴子的更新数量:
#!/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()
关于python - 如何从不同线程的事件更新 Gtk.TextView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39556006/