如何更新文本视图从另一个线程的事件?

2024-04-19 06:23:34 发布

您现在位置:Python中文网/ 问答频道 /正文

在一个单独的线程中,我检查pySerial缓冲区(无限循环)中的信息。如果有新的信息可用,我想在Gtk.TextView中显示该输入。在google上搜索这个主题后,发现在线程中做Gtk-Stuff是个杀手。随机错误会出现等等,这也是我遇到的一个问题。在

我决定使用一个队列来同步线程和GUI。将信息放入队列非常简单,但是如果队列中有任何条目,我应该如何检查主循环?在

如果有新的信息可以触发一些事件。在

有那种东西吗?可能存在一个函数来实现GTK3+mainloop中的自定义python代码?在


Tags: 函数信息gtk主题队列错误google事件
2条回答

找到了解决方案:

GObject.timeout_add

http://www.pygtk.org/pygtk2reference/gobject-functions.html#function-gobject timeout-add

此GObject函数每隔X毫秒实现一次对自己函数的回调。在这里找到了一个非常简单的解释:

https://gist.github.com/jampola/473e963cff3d4ae96707

所以我可以每隔X毫秒把从队列收集到的所有信息都记录下来。处理线程的好方法!在

为了从线程中的事件成功地定期更新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(),我们几乎有了如何在Gtk应用程序中运行线程的更新版本。一个简化的示例,显示文本字段中猴子数量的增加。请参见代码中的注释:

例如,计算文本视图中更新的猴子数量:

enter image description hereenter image description hereenter 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()
        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()

相关问题 更多 >