Python GUI 直到整个进程完成才更新

2 投票
3 回答
3782 浏览
提问于 2025-04-16 11:29

我有一个程序,它会从一个文件夹里获取文件,并把这些文件放到一个列表里。接着,它会在一个循环中逐个处理这个列表。循环的最后一行是更新我的图形界面(gui),然后再开始处理列表中的下一个项目。

我的问题是,图形界面实际上要等整个过程完成后才会更新,而这个过程可能需要30秒到一分钟,具体取决于列表的大小。这让人感觉程序好像“卡住”了。

我希望它能处理列表中的一项,更新图形界面,然后继续处理下一项。我哪里做错了呢?更新列表的那一行是 # Populate listview with drive contents。打印语句只是用来调试的。

def populateList(self):
    print "populateList"

    sSource = self.txSource.Value
    sDest = self.txDest.Value

    # re-intialize listview and validated list
    self.listView1.DeleteAllItems()
    self.validatedMove = None
    self.validatedMove = []

    #Create list of files
    listOfFiles = getList(sSource)    

    #prompt if no files detected
    if listOfFiles == []:
        self.lvActions.Append([datetime.datetime.now(),"Parse Source for .MP3 files","No .MP3 files in source directory"])

    #Populate list after both Source and Dest are chosen
    if len(sDest) > 1 and len(sDest) > 1:     
        print "-iterate listOfFiles"

        for file in listOfFiles:
            sFilename = os.path.basename(file)
            sTitle = getTitle(file)
            sArtist = getArtist(file)
            sAlbum = getAblum(file)

            # Make path = sDest + Artist + Album
            sDestDir = os.path.join (sDest, sArtist)
            sDestDir = os.path.join (sDestDir, sAlbum) 

            #If file exists change destination to *.copyX.mp3
            sDestDir = self.defineDestFilename(os.path.join(sDestDir,sFilename))

            # Populate listview with drive contents       
            self.listView1.Append([sFilename,sTitle,sArtist,sAlbum,sDestDir])

            #populate list to later use in move command
            self.validatedMove.append([file,sDestDir])
            print "-item added to SourceDest list"
    else:
        print "-list not iterated"

3 个回答

0

我建议你试试 wx.lib.delayedresult。这个东西可以算是简化版的多线程解决方案。你可以把你的业务逻辑放在一个工作函数里,而其他的逻辑(比如更新界面)放在一个消费函数里。工作函数会在另一个线程中运行,而消费函数则保证在工作函数完成后在主线程中运行。

3

创建一个工作线程或进程,让它在后台进行处理,处理完成后再更新图形界面,可能在工作过程中还会报告进度。

可以看看 threadingmultiprocessing 这两个模块。

3

这是一个常见的图形界面程序问题。界面上的控件(比如按钮、文本框等)不会自动更新,直到收到并处理一个“重绘”的命令,而这个命令通常是在你的函数执行完之后才会发出。

不过,你可以随时通过调用控件的 Update 方法来强制控件进行重绘。具体的做法可以参考这个问题的回答: 如何强制刷新 wx.Panel?

撰写回答