进度条在操作期间不更新

时间:2009-01-30 19:17:39

标签: python user-interface gtk progress-bar pygtk

在我的python程序中将文件上传到互联网,我使用GTK进度条显示上传进度。但是我面临的问题是进度条在上传完成之前没有显示任何活动,然后它突然表示上传完成。即时通讯使用pycurl来发出http请求...我的问题是 - 我是否需要一个多线程应用程序来上传文件并同时更新gui?或者是否还有其他错误?

提前致谢!

5 个答案:

答案 0 :(得分:12)

我要引用PyGTK FAQ

  

您已在窗口中创建了一个进度条,然后开始运行一个可以完成某项工作的循环:

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处于控制状态,而idle函数必须做一些工作。如果还有更多的工作要做,它应该返回True,否则返回False。

     

James Henstridge指出了最好的解决方案(没有任何缺点)。它利用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)
  

上面的'while'只是一个例子。唯一的规则是它应该在完成一些工作后产生True并且还有更多的工作要做,并且在任务完成时它必须产生False。

答案 1 :(得分:1)

更有可能的问题是,在你的进程回调中,我认为你正在更新进度条,你没有调用手动更新显示,即通过GUI的事件循环运行。这只是猜测,如果你能提供更多代码,可能更容易进一步缩小代码。

您需要手动更新显示的原因是因为您的主线程也在执行上传,这是阻止它的位置。

答案 2 :(得分:0)

在python 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)

答案 3 :(得分:0)

是的,您可能需要并发,并且是线程是一种方法,但如果您使用线程,请使用类似这样的方法:http://unpythonic.blogspot.com/2007/08/using-threads-in-pygtk.html这将消除痛苦,并让您专注于重要的方面。

(我没有在博客文章中通过懒惰重复一切,因此社区维基)。

答案 4 :(得分:0)

如果你没有与pycurl结婚,一个选择是使用GObject的IO观察者。

http://pygtk.org/pygtk2reference/gobject-functions.html#function-gobject--io-add-watch

使用此方法,您可以将文件上传与普通的PyGTK事件循环交错,甚至可以在IO监视回调中执行set_progress调用。如果你正在卸载上传到pycurl的所有工作,这实际上是不可行的,但如果你只是通过HTTP上传文件,io_add_watch将使用套接字来减轻这种痛苦。