我正在用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对象的事情。
谢谢
答案 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()