简体   繁体   English

PySide / Python GUI冻结

[英]PySide / Python GUI freezes

I'm currently writing a GUI for rvplayer that shall enable artists to automatically render dailies with slate and burn-in information. 我目前正在为rvplayer编写一个GUI,它可以让艺术家自动使用平板和老化信息来呈现样片。 The GUI is written with PySide and scripted in Python 2.7. GUI使用PySide编写,并在Python 2.7中编写脚本。 My problem is that upon calling my process and updating my QProgressBar with the stdout the GUI freezes. 我的问题是,在调用我的进程并使用stdout更新我的QProgressBar ,GUI会冻结。 I know that this is a common problem and that it can probably be solved with processEvents() somehow, but I know far too little about threading and process loops to get my head around this issue. 我知道这是一个常见的问题,它可能会以某种方式解决processEvents() ,但我对线程和进程循环知之甚少,无法解决这个问题。 Since my code is a little lengthy already, here's the part that causes the issue: 由于我的代码已经有点冗长,因此导致问题的部分是:

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

and here is the part that starts my QApplication : 这是启动我的QApplication的部分:

if __name__ == "__main__":

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

I'm calling the function rv upon pressing a button and although the progress bar keeps updating normally, the window starts to get nonresponsive after some time. 我按下按钮调用函数rv,虽然进度条保持正常更新,但窗口在一段时间后开始无响应。 I do not understand at which point I could use app.processEvents() to tell my QApplication to run the process in a separate thread or in the background. 我不明白我可以使用app.processEvents()告诉我的QApplication在单独的线程或后台运行该进程。

Since it looks like you're not using threads, it may be that all that's required is to call processEvents after updating the progress bar, like this: 因为看起来你没有使用线程,所以所需要的只是在更新进度条后调用processEvents ,如下所示:

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

However, the effectiveness of this may depend on how long it takes the process to produce the output. 但是,这种效果可能取决于生产输出过程需要多长时间。 All that the processEvents call does is to immediately handle any pending events (eg widget painting, mouse clicks, etc) that are currently in the application's event queue. processEvents调用的所有操作都是立即处理当前在应用程序事件队列中的任何挂起事件(例如,小部件绘制,鼠标单击等)。 In between those calls, the GUI will continue to freeze (ie the executing code is not run in a separate thread or in the background, as you suggested). 在这些调用之间,GUI将继续冻结(即执行代码不在单独的线程中或在后台运行,如您所建议的那样)。 So the extent to which this technique can keep the GUI responsive depends on how frequently processEvents can be called within the rv() method. 因此,此技术可以保持GUI响应的程度取决于在rv()方法中调用processEvents频率。

The issue is that it's not as if your app is frozen, but Windows thinks that the app is frozen as it's ignoring events (mouse over, click etc etc), so Windows, in its wisdom, gives you that dialogue. 问题是,它不像你的应用程序被冻结,但是Windows认为该应用程序被冻结,因为它忽略了事件(鼠标悬停,点击等等),因此Windows以其智慧为您提供了对话。

You need to start the thread off after the show() and then run the processEvents function, and obviously only call sys.exit once your thread has finished. 你需要在show()之后启动线程然后运行processEvents函数,显然只有在线程完成后才调用sys.exit。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM