Python Четыре шага установки с прогрессбаром - PullRequest
1 голос
/ 16 мая 2010

У меня проблема с кодом ниже. Когда я его запускаю, индикатор выполнения будет пульсировать около 10 секунд, а затем перейдет к загрузке и покажет прогресс, но по окончании он не перейдет к следующему шагу и просто заблокируется.

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): # when does "run" get executed?
        self.parent.still_working = True      
        if self.arg == 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)

        while gtk.events_pending():
            gtk.main_iteration()

    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()

У меня такое ощущение, что это как-то связано с:

while gtk.events_pending():
    gtk.main_iteration()

Есть ли лучший способ сделать это?

1 Ответ

1 голос
/ 28 мая 2010

Никогда не делай этого:

while gtk.events_pending():
   gtk.main_iteration()

Если вы действительно не знаете, что делаете. И если вы действительно делаете, сделайте это , как это :

def refresh_gui(delay=0.0001, wait=0.0001):
    """Use up all the events waiting to be run

    :param delay: Time to wait before using events
    :param wait: Time to wait between iterations of events

    This function will block until all pending events are emitted. This is
    useful in testing to ensure signals and other asynchronous functionality
    is required to take place.

    (c) PyGTKHelpers Authors 2005-2010
    """
    time.sleep(delay)
    while gtk.events_pending():
        gtk.main_iteration_do(block=False)
        time.sleep(wait)

с использованием block = False и некоторых задержек.

Если вы хотите использовать потоки, я лично не рекомендовал бы создавать подклассы Thread таким образом (нет никакого смысла), вместо этого я бы посоветовал подход , подобный этому , который имеет пример обновления прогресса бар.

...