- 在使用 Python 代码设置四步进度条时,遇到的问题如下:
- 进度条在开始时会跳动 10 秒左右,然后开始下载并显示进度。
- 下载完成后,进度条卡住不动,无法进行下一步操作。
- 解决方案
答案中给出的解决方案如下:
- 不要使用
while gtk.events_pending(): gtk.main_iteration()来更新 GUI,这是不推荐的做法。 - 可以使用
refresh_gui()函数来更新 GUI,该函数可以阻塞直到所有待处理事件都被触发。 - 推荐使用线程来处理耗时操作,而不是继承
Thread类。
代码示例
import sys
import time
import pygtk
import gtk
import gobject
import threading
import urllib
import urlparse
class WorkerThread(threading.Thread):
def __init__(self, function, parent, arg=None):
threading.Thread.__init__(self)
self.function = function
self.parent = parent
self.arg = arg
self.parent.still_working = True
def run(self): # 当执行 "run" 时
self.parent.still_working = True
if self.arg is None:
self.function()
else:
self.function(self.arg)
self.parent.still_working = False
def stop(self):
self = None
class MainWindow:
def __init__(self):
gtk.gdk.threads_init()
self.wTree = gtk.Builder()
self.wTree.add_from_file("gui.glade")
self.mainWindows()
def mainWindows(self):
self.mainWindow = self.wTree.get_object("frmMain")
dic = {
"on_btnNext_clicked": self.mainWindowNext,
}
self.wTree.connect_signals(dic)
self.mainWindow.show()
self.installerStep = 0 # 0 = none, 1 = preinstall, 2 = download, 3 = install info, 4 = install
# gtk.main()
self.mainWindowNext()
def pulse(self):
self.wTree.get_object("progress").pulse()
if self.still_working == False:
self.mainWindowNext()
return self.still_working
def preinstallStep(self):
self.wTree.get_object("progress").set_fraction(0)
self.wTree.get_object("btnNext").set_sensitive(0)
self.wTree.get_object("notebook1").set_current_page(0)
self.installerStep = 1
WT = WorkerThread(self.heavyWork, self) # Would do a heavy function here like setup some thing
WT.start()
gobject.timeout_add(75, self.pulse)
def downloadStep(self):
self.wTree.get_object("progress").set_fraction(0)
self.wTree.get_object("btnNext").set_sensitive(0)
self.wTree.get_object("notebook1").set_current_page(0)
self.installerStep = 2
urllib.urlretrieve('http://mozilla.mirrors.evolva.ro//firefox/releases/3.6.3/win32/en-US/Firefox%20Setup%203.6.3.exe', '/tmp/firefox.exe', self.updateHook)
self.mainWindowNext()
def updateHook(self, blocks, blockSize, totalSize):
percentage = float(blocks * blockSize) / totalSize
if percentage > 1:
percentage = 1
self.wTree.get_object("progress").set_fraction(percentage)
gtk.main_iteration_do(block=False)
def installInfoStep(self):
self.wTree.get_object("btnNext").set_sensitive(1)
self.wTree.get_object("notebook1").set_current_page(1)
self.installerStep = 3
def installStep(self):
self.wTree.get_object("progress").set_fraction(0)
self.wTree.get_object("btnNext").set_sensitive(0)
self.wTree.get_object("notebook1").set_current_page(0)
self.installerStep = 4
WT = WorkerThread(self.heavyWork, self) # Would do a heavy function here like setup some thing
WT.start()
gobject.timeout_add(75, self.pulse)
def mainWindowNext(self, widget=None):
if self.installerStep == 0:
self.preinstallStep()
elif self.installerStep == 1:
self.downloadStep()
elif self.installerStep == 2:
self.installInfoStep()
elif self.installerStep == 3:
self.installStep()
elif self.installerStep == 4:
sys.exit(0)
def heavyWork(self):
time.sleep(10)
if __name__ == '__main__':
MainWindow()
gtk.main()