Here is some sample code that breaks:
import sys
import time
from PyQt5.QtWidgets import (QApplication, QDialog,
QProgressBar)
class Actions(QDialog):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.progress = QProgressBar(self)
self.progress.setGeometry(0, 0, 300, 25)
self.show()
self.count = 0
while self.count < 100:
self.count += 1
time.sleep(1) # Example external function
self.progress.setValue(self.count)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Actions()
sys.exit(app.exec_())
Running this will cause it to freeze and become unresponsive particularly in windows environments. Replacing the time.sleep
function with any non-PyQt5 function will yield the same results.
From what I understand this has to do with the function not being called in a separate thread using QThread. I used this answer as a reference and came up with a partial solution.
import sys
import time
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import (QApplication, QDialog,
QProgressBar)
class External(QThread):
def run(self):
count = 0
while count < 100:
count += 1
print(count)
time.sleep(1)
class Actions(QDialog):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.progress = QProgressBar(self)
self.progress.setGeometry(0, 0, 300, 25)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Actions()
calc = External()
calc.finished.connect(app.exit)
calc.start()
sys.exit(app.exec_())
This will run time.sleep
in the background and keep the main window responsive. But, I don't know how to update the values using self.progress.setValue
since it's not accessible in class External
.
So far from what I know, I have to use signals to accomplish this. Most of the documentation out there is for PyQt4 making it harder to find a solution.
Another problem I am faced with is being able to start the External
thread from within class Actions
.
Answers to this problem will also serve as valuable documentation for PyQt5. Thanks in advance.