更新wx.Gauge并保持当前帧活着?

时间:2013-09-03 18:43:45

标签: python multithreading wxpython

我正在编写一个使用python和wxpython从网站下载文件的小工具。 我已经把一切都搞定了,唯一让我烦恼的是,我想用一个进度条来显示完成情况,在urlretrieve之后,唯一正在移动的是进度条,GUI只是变得没有响应。我知道这与线程有关,但我对此非常陌生。有人可以给我一个暗示吗?

这个想法是在主框架上我从网站获得搜索结果,并将结果提供给此DownloadListingFrame,然后它会动态生成按钮和staticText。问题是点击下载按钮后,进度条更新为文件正在下载,但除此之外整个应用程序挂起。在从其他示例中读取其他人的代码后,我想我将doDownload函数放在一个线程中并执行它,它的行为与不使用线程的行为相同......

先谢谢。

类DownloadListingFrame(wx.Frame):

data = ''

def __init__( self, parent, result ):
    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u'result', pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
    self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

    self.statusbar = self.CreateStatusBar()
    self.statusbar.SetFieldsCount(3)

    self.progessBar = wx.Gauge(self.statusbar, -1, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH)
    rect = self.statusbar.GetFieldRect(1)
    self.progessBar.SetPosition((rect.x+2, rect.y+2 ))
    self.progessBar.SetSize((rect.width, rect.height-4))

    buttonPos = 20
    for item in result:
        label = wx.StaticText( self, wx.ID_ANY, item, wx.Point( 120 ,buttonPos+2 ), wx.DefaultSize, 0 )
        button = wx.Button(self, id=-1,label=u'Download', pos=(20, buttonPos))
        buttonPos = buttonPos + 30
        self.Bind(wx.EVT_BUTTON, lambda x: self.Downloader(item, result[item]), button)

    self.Centre( wx.BOTH )


def progressUpdate(self, blockCount, blockSize, totalSize):
    progressSoFar = int((float(blockCount) * float(blockSize) / float(totalSize)) * 100)
    self.progessBar.SetValue(progressSoFar)

def doDownloade(self, realAddress, saveAsFilename):
    urllib.urlretrieve(realAddress, saveAsFilename, self.progressUpdate)

def Downloader(self, title, url):
    saveAsPath = wx.DirDialog(self, u"save to...")
    if saveAsPath.ShowModal() == wx.ID_OK:
        realAddress = self.getRealAddress(url)
        saveAsFilename = os.path.join(saveAsPath.GetPath(), title + os.path.splitext(realAddress)[1])
        thread = threading.Thread(target=self.doDownloade(realAddress, saveAsFilename))
        thread.setDaemon(True)
        thread.start()

def getRealAddress(self, url):
    import httplib
    siteUrl = 'www.yyets.com'
    httpConnection = httplib.HTTPConnection(siteUrl)
    httpConnection.request("GET", url)
    resp = httpConnection.getresponse()
    realAddress = resp.getheaders()[6][1]
    return realAddress

def __del__( self ):
    pass

1 个答案:

答案 0 :(得分:1)

运行命令时:

thread = threading.Thread(target=self.doDownloade(realAddress, saveAsFilename))

首先运行self.doDownloade(realAddress, saveAsFilename),然后将此返回值(将为None)作为目标传递。

相反,你想:

thread = threading.Thread(target=self.doDownloade, args=(realAddress, saveAsFilename))

注意,在这里,我已经通过了功能 self.doDownloade,然后thread将使用您拨打时给出的agrs来调用{ {1}}。

顺便说一句,您也可以使用thread.start执行此操作。我通常认为这是更好的仪表工具,因为它更容易,您可以控制仪表更新的频率,因此可以控制仪表使用多少资源。主要的wxPython演示测量示例使用wx.Timer,你想要一个很好的起点。