In my GUI I have a button which starts a subprocess to execute an Abaqus job. I have a QObject worker subclass to read the resulting .sta and .inp files and emit to pyqtSignal's some results to methods for updating the statusbar and progressbar.
I set the QThread / worker up based on this stackoverflow answer: https://stackoverflow.com/a/54458277/17337814, and at one point it was working perfectly but after some changes it's broken.
My progressbar will update correctly but if I touch anything on the GUI it freezes until the thread is closed. The statusbar message doesn't update at all, but the progress bar does change color when completed. I also have yet to test if the progress bar will update correctly if running multiple times...
Some code (sorry cannot provide entire code):
#subclass_module.py
class AbaqusProgress(QObject):
finished = pyqtSignal()
progress = pyqtSignal(int)
message = pyqtSignal(str)
completed = pyqtSignal(bool)
def run(self, inp_path, wait_time=5):
step_dict = self.return_steps(inp_path)
i = 0
status = None
while status is None:
print(i)
if wait_time * i / 60 > 10:
status = 'TIMEOUT'
msg = 'Warning: Progress bar timed out after 15 minutes'
QThread.sleep(wait_time)
i += 1
percent, step_name = self.return_percent(inp_path, step_dict)
if percent < 0:
percent = abs(percent)
msg = 'Error: Simulation failed to converge'
status = False
elif percent == 100:
msg = 'Simulation completed successfully'
status = True
else:
msg = 'Simulation running, current step: ' + step_name
self.progress.emit(percent)
self.progress.emit(msg)
self.completed.emit(status)
self.finished.emit()
def return_percent(self, ...):
...
def return_steps(self, ...):
...
class MyMainWindow(QMainWindow):
...
#myGUI_module.py
class myGUI(MyMainWindow):
def __init__(self):
super().__init__(<args for MyMainWindow>)
self._thread = QThread(self)
self._worker = myqt.AbaqusProgress()
self._worker.moveToThread(self._thread)
self._worker.progress.connect(self.progress_bar.setValue)
self._worker.message.connect(self.status_bar.showMessage)
self._worker.completed.connect(self.pb_chunk)
self._thread.finished.connect(self._worker.deleteLater)
...
...
def button_function(self):
self.update_data()
temp = os.getcwd()
inp = self.data['path'] + '\\file.inp'
sta = inp_path.replace('.inp', '.sta')
if os.path.exists(sta):
os.remove(sta)
try:
os.chdir(self.data['path'])
tools.run_abaqus(inp,
abaqus_path=self.data['abaqus_path'])
self._thread.start()
QTimer.singleShot(1, lambda: self._worker.run(inp))
os.chdir(temp)
except FileNotFoundError:
self.output_msg('Error: Project directory is incorrect '
+ 'or does not exist')
def pb_chunk(self, completed):
color = 'green' if completed else 'red'
self.progress_bar.setStyleSheet(
'QProgressBar::chunk{background-color:' + color + '}')
def closeEvent(self, event):
if self._thread.isRunning():
self._thread.quit()
del self._thread
del self._worker
super(myGUI, self).closeEvent(event)
...
Can you identify why these problems are occurring?
Thank you!!
I've tried:
Using self._thread.finished.connect(lambda: worker.run(args)) in the myGUI init instead of the QTimer.singleshot() (no change but complicates arg transfer)
Some other things but I've forgotten them...