nuki
nuki

Reputation: 75

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. The GUI is written with PySide and scripted in Python 2.7. My problem is that upon calling my process and updating my QProgressBar with the stdout the GUI freezes. 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. 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:

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. 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.

Upvotes: 3

Views: 2516

Answers (2)

ekhumoro
ekhumoro

Reputation: 120628

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:

    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 (e.g. widget painting, mouse clicks, etc) that are currently in the application's event queue. In between those calls, the GUI will continue to freeze (i.e. the executing code is not run in a separate thread or in the background, as you suggested). So the extent to which this technique can keep the GUI responsive depends on how frequently processEvents can be called within the rv() method.

Upvotes: 3

Richard Green
Richard Green

Reputation: 2062

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.

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.

Upvotes: 0

Related Questions