在 Python 中处理线程上的 GTK 对象

Handling GTK Objects on Threads in Python

我正在 Python 中创建一个应用程序,它使用 GTK 来构建 UI,并且我不太清楚在线程上处理 GTK 对象,例如 GtkProgressBar 对象。

上下文如下:

我尝试在主线程上进行下载,我添加了一个 GObject.timeout_add 来脉冲条,直到下载结束。但是在第一个脉冲之后 UI 冻结了。

直到出现OK,线程冻结,直到下载完成,所以任何组件都会被更新。解决方案:创建一个新线程。

我创建了这个新线程来进行下载和其他操作。在此线程上,我收到进行更新的进度条。但是当下载是 运行 并且我添加 GObject.timeout_add 来脉冲条时,UI 再次冻结。新解决方案:创建第三个线程。

所以我的线程看起来像这样:

Main-Thread
    '---- Thread 1
             '------Thread 2

所以,在 Thread 1 上,我做了另一件事并更新了 UI,而在 Thread 2 上,我进行了下载并添加了 GObject.timeout_add 并在那里我可以更新进度条。在 Thread 1 我加入了 Thread 2

我使用 GObject.idle_add 函数处理 Gtk 对象。

但是我很困惑为什么进度条的下载和更新在 Thread 2 上运行良好而在 Thread 1

上运行良好

有人可以向我解释为什么会这样,或者如果我错过了有关处理 GTK 对象的内容。

谢谢

如果您阻止 Gtk 主循环,window 和小部件将变得无响应。这就是为什么您不能在主线程中进行下载的原因。从下载线程更新 Gtk.ProgressBar 可能会起作用,具体取决于您的实现方式。

这是一种下载内容并使 ProgressBar 正常工作的方法:

from gi.repository import Gtk, GLib
import threading
import urllib.request

class Window(Gtk.Window):
    def __init__(self):
        super().__init__()
        self.connect('delete-event', Gtk.main_quit)
        self.progress = Gtk.ProgressBar()
        self.add(self.progress)
        self.show_all()

        # Start download
        self.thread = threading.Thread(target=self.download)
        self.thread.start()
        GLib.timeout_add_seconds(1, self.download_pulse)

    def download(self):
        urllib.request.urlretrieve('<link>')

    def download_pulse(self):
        if self.thread.is_alive():
            self.progress.pulse()
            return True
        return False

win = Window()
Gtk.main()