How can I implement a progress bar in a pop-up window that monitors the progress of a running function from a so-called Worker class (i.e. time
To understand the problem you must know that the following:
self.main_window_button.clicked.connect(PopUpProgressB)
Equivalent to:
self.main_window_button.clicked.connect(foo)
# ...
def foo():
PopUpProgressB()
Where it is observed that when pressing the button a PopUpProgressB object is created that does not have a life cycle just like the execution of the "foo" function that is practically instantaneous so the popup will be shown and hidden in a very short time.
The idea is that the popup has a scope that allows it to have a life cycle large enough to show the progress for it should be made to the class attribute popup object.
# ...
self.main_window_button = QPushButton("Start")
self.popup = PopUpProgressB()
self.main_window_button.clicked.connect(self.popup.show)
self.h_box.addWidget(self.main_window_button)
# ...
And so that it doesn't show you must remove the call to the show() method of PopUpProgressB:
class PopUpProgressB(QWidget):
def __init__(self):
super().__init__()
# ...
self.setWindowTitle('Progress Bar')
# self.show() # <--- remove this line
self.obj = Worker()
# ...
Since I already explained the failure of your problem I will answer your questions:
Why does it crash? When the popup object is deleted, the created QThread is also deleted but Qt accesses no longer allocated memory (core dumped) causing the application to close without throwing any exceptions.
Why does it work during debugging? Many IDEs like PyCharm do not handle Qt errors, so IMHO recommends that when they have such errors they execute their code in the terminal/CMD, for example when I execute your code I obtained:
QThread: Destroyed while thread is still running
Aborted (core dumped)
Should I just give up and implement the progress bar (anchored) in the main window of the app? No.
I already implemented a similar thing in the past but without threading: within the loop of the worker function (i.e. CPU-consuming function) I had to add QApplication.processEvents() so that at each iteration the progressbar was effectively updated. It is apparently suboptimal to do things this way. Is it still a better alternative to what I am trying to achieve now? Do not use QApplication::processEvents() if there are better alternatives, in this case the threads is the best since it makes the main thread less busy.
Finally, many of the errors that beginners report in Qt refer to the scope of the variables so I recommend you analyze how much it should be for each variable, for example if you want an object to live the same as the class then make that variable is an attribute of the class, if instead you only use it in a method then it is only a local variable, etc.