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

时间:2015-10-29 21:47:50

标签: python multithreading pygtk pygobject

我正在用Python创建一个应用程序,它使用GTK来构建UI,我对在线程上处理GTK对象感到困惑,例如,GtkProgressBar对象。

以下是上下文:

我尝试在主线程上进行下载,并添加GObject.timeout_add以激活条形码直到下载结束。但是在第一次脉冲之后,用户界面冻结了。

直到确定,线程冻结直到下载完成,因此任何组件都将更新。解决方案:创建一个新线程。

我已经创建了这个新线程来制作下载和其他东西。在这个帖子中,我收到进度条来进行更新。但是当下载正在运行并且我添加GObject.timeout_add以激活条形图时,UI再次冻结。新解决方案:创建第三个线程。

所以我的线程正在寻找这个:

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

所以,在Thread 1上,我做了另外的事情并更新了用户界面,而在Thread 2我进行了下载并添加了GObject.timeout_add,在那里我可以更新进度条。在Thread 1我加入Thread 2

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

但我很担心为什么下载和进度条的更新在Thread 2而不是Thread 1

上运行良好

有人可以向我解释为什么会发生这种情况,或者我是否会错过处理GTK对象的事情。

谢谢

1 个答案:

答案 0 :(得分:2)

如果阻止Gtk主循环,则窗口和小部件将无响应。这就是为什么你不能在主线程中进行下载。从下载线程更新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()