PySide / Python GUI冻结

3

我正在编写一个GUI界面,用于rvplayer的自动渲染日报和附带信息。这个GUI界面是使用PySide编写并在Python 2.7中进行脚本编写的。我的问题是,在调用进程并使用stdout更新我的QProgressBar时,GUI界面会冻结。我知道这是一个常见的问题,可能可以通过processEvents()解决,但我对线程和进程循环知之甚少,无法理解这个问题。由于我的代码已经有点长了,这里是导致问题的部分:

def rv(self, args):
    p = subprocess.Popen(["C:/Program Files/Tweak/RV-4.0.10-64/bin/rvio_hw.exe"]+[x for x in args], stdout=subprocess.PIPE)
    while True:
        line = p.stdout.readline()
        if line != "":
            progressStr=re.search(r"([0-9]+.[0-9]+%)", line.rstrip())
            if progressStr == None:
                print line.rstrip()
            else:
                progressInt=int(float(re.sub("[^0123456789\.]", "", progressStr.group())))
                self.prog_QProgressBar.setValue(progressInt)
                print progressStr.group()
        else:       
            break

这里是开始我的QApplication的部分:

if __name__ == "__main__":

    app = QtGui.QApplication(sys.argv)
    finalForm = MainWindow()
    finalForm.show()
    sys.exit(app.exec_())

我在按下按钮时调用了函数rv,虽然进度条正常更新,但窗口在一段时间后开始失去响应。我不明白何时可以使用 app.processEvents() 来告诉我的 QApplication 在单独的线程或后台运行该过程。


我想知道如果在后台线程中运行它是否也会发生这种情况?更多细节请参见https://dev59.com/yGw15IYBdhLWcg3wLIo2#22060122。 - Trilarion
你可以在这里找到一篇关于你问题的好文章:http://doc.qt.digia.com/qq/qq27-responsive-guis.html - marsh
2个回答

3

看起来您没有使用线程,只需要在更新进度条后调用processEvents即可,代码如下:

    self.prog_QProgressBar.setValue(progressInt)
    QtGui.qApp.processEvents()

然而,这种方法的有效性可能取决于该过程产生输出需要多长时间。 processEvents 调用所做的一切只是立即处理当前应用程序事件队列中存在的任何挂起事件(例如小部件绘制、鼠标点击等)。在这些调用之间,GUI 将继续冻结(即执行代码不在单独线程或后台运行,正如您所建议的那样)。因此,这种技术可以使 GUI 保持响应的程度取决于 rv() 方法内可以多频繁地调用 processEvents

0
问题在于,你的应用程序并没有冻结,但Windows认为应用程序冻结了,因为它忽略了事件(鼠标悬停、点击等),所以Windows聪明地给出了对话框。
你需要在show()之后启动线程,并运行processEvents函数,并且只有在线程完成后才调用sys.exit。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接