操作过程中的进度条不更新
-
20-08-2019 - |
题
在我的Python程序使用GTK进度条显示上传进度将文件上传到互联网,即时通讯。但是,即时通讯面临的问题是,进度条不显示任何活动,直到上载完成,然后它突然表示上传完成。即时通讯使用pycurl使http请求...我的问题是 - 我是否需要有一个多线程应用程序上传的文件,并同时更新GUI?或者是有,即时通讯做一些其他的错误吗?
提前感谢!
解决方案
我要引用 PyGTK的常见问题解答:
您已经创建了一个窗口内的进度条,然后你开始运行一个循环,做了一些工作:
while work_left:
...do something...
progressbar.set_fraction(...)
您会发现窗口甚至不出现,或者如果它的进度条仍然冻结,直到任务结束。原因很简单:GTK是事件驱动的,并且您窃取控制从GTK主循环远,从而防止它从处理正常GUI更新事件
的最简单的解决方案包括对暂时使控制返回到GTK每过程中改变时间:
while work_left:
...do something...
progressbar.set_fraction(...)
while gtk.events_pending():
gtk.main_iteration()
请注意,这种解决方案中,用户不能退出该应用程序(因为新的循环gtk.main_quit是行不通[gtk.main_iteration()]),直到你heavy_work完成。
另一解决方案包括使用GTK空闲功能,这是由所谓的GTK主循环每当它无关。因此,GTK是在控制和空闲功能必须做一些工作。它应该返回true,如果有需要做更多的工作,否则假。
最好的解决办法(它没有缺陷)由James亨斯特莱吉指出。它是利用Python的发电机的闲置功能,使Python自动保存状态我们。它是这样的:
def my_task(data):
...some work...
while heavy_work_needed:
...do heavy work here...
progress_label.set_text(data) # here we update parts of UI
# there's more work, return True
yield True
# no more work, return False
yield False
def on_start_my_task_button_click(data):
task = my_task(data)
gobject.idle_add(task.next)
在“而”以上仅仅是一个例子。唯一的规则是它应该做一些工作后产生真正的,有更多的工作要做,而当任务完成后,必须产生错误的。
其他提示
更可能的问题是,在你的进步的回调,这是我想你要更新进度条,你不是在打电话手动更新的显示,即通过GUI的事件循环运行。这仅仅是猜测不过,如果你能提供更多的代码,它可能更容易进一步缩小范围。
原因您需要手动更新显示是因为你的主线程也进行上传,这是它的阻止。
在蟒2.x的整数操作数导致整数除法。尝试这样:
#Callback function invoked when download/upload has progress
def progress(download_t, download_d, upload_t, upload_d):
print 'in fileupload progress'
mainwin.mainw.prog_bar.set_fraction(float(upload_d) / upload_t)
是的,你可能需要的并发,是的线程是一种方法,但如果你使用线程,请使用方法类似这样的:的 http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html ,以抽象掉疼痛,让您专注于重要方面。
(我没有通过懒惰该博客文章重复的一切,因此社区维基)。
一个选项,如果你不结婚pycurl,是使用GObject的IO观察家。
http://pygtk.org/ pygtk2reference / GObject的-functions.html#函数的GObject - IO-附加观看
使用这个你可以交错与正常的PyGTK事件循环的文件上传,甚至做你的IO手表回调set_progress电话。如果您卸载所有的工作上传到pycurl这是不是真的可行的,但如果你只是上传通过HTTP文件,io_add_watch将使用套接字这么多痛苦少为好。