Почему вы создаете 2 темы?
Задача CalculationProgressBar не является тяжелой, поскольку его задача состоит только в том, чтобы показать данные, которые он получает из другого потока, кроме того, что графический интерфейс не может перейти в другой поток. Вам просто нужно создать отдельный поток , в котором будет жить объект класса Calculation.
Нет необходимости подключать сигнал запуска для запуска задачи, достаточно вызвать сигнал сигналом, как показано. С другой стороны, нет необходимости создавать CalculationProgressBar при каждом нажатии кнопки, лучше всего использовать его повторно.
Учитывая вышеизложенное, решение выглядит так:
# -*- coding: utf-8 -*-
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QThread
from PyQt5 import QtWidgets
from sys import exit, argv
from time import sleep
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.open_progress_bar_button = QtWidgets.QPushButton('Open calculate bar', self)
self.open_progress_bar_button.resize(self.open_progress_bar_button.sizeHint())
self.open_progress_bar_button.move(100, 50)
self.open_progress_bar_button.clicked.connect(self.run_calculation_thread)
self.calculation_progress_bar = CalculationProgressBar()
self.calculation_progress_bar.close_progress_bar.connect(self.on_close_create_progress_bar_thread)
self.setGeometry(500, 300, 300, 100)
self.setWindowTitle('MainWindow')
self.show()
def run_calculation_thread(self):
self.open_progress_bar_button.setEnabled(False)
self.calculation_progress_bar.progress_bar.reset()
self.calculation_progress_bar.show()
def on_close_create_progress_bar_thread(self):
self.open_progress_bar_button.setEnabled(True)
class CalculationProgressBar(QtWidgets.QWidget):
request_calculation = pyqtSignal()
close_progress_bar = pyqtSignal()
def __init__(self, parent=None, **kwargs):
super().__init__(parent, **kwargs)
self.calculation_thread = QThread(self)
self.calculation_thread.start()
self.calculation = Calculation()
self.calculation.moveToThread(self.calculation_thread)
self.calculation.notify_progress.connect(self.on_progress)
self.calculation.calculation_done.connect(self.on_finish)
self.request_calculation.connect(self.calculation.calculate)
QtWidgets.qApp.aboutToQuit.connect(self.calculation_thread.quit)
self.setup_gui()
def setup_gui(self):
l = QtWidgets.QVBoxLayout(self)
self.progress_bar = QtWidgets.QProgressBar(self)
self.progress_bar.setTextVisible(False)
self.progress_bar.setRange(0, 100)
l.addWidget(self.progress_bar)
self.open_progress_bar_button = QtWidgets.QPushButton("Calculate", self, clicked=self.tables_creation_requested)
l.addWidget(self.open_progress_bar_button)
self.setFixedWidth(300)
def reset(self):
self.progress_bar.setValue(0)
@pyqtSlot(int)
def on_progress(self, i):
self.progress_bar.setValue(i)
@pyqtSlot()
def on_finish(self):
self.hide()
self.close_progress_bar.emit()
self.open_progress_bar_button.setEnabled(True)
@pyqtSlot()
def tables_creation_requested(self):
self.request_calculation.emit()
self.open_progress_bar_button.setEnabled(False)
class Calculation(QObject):
notify_progress = pyqtSignal(int)
calculation_done = pyqtSignal()
@pyqtSlot()
def calculate(self):
for i in range(3):
self.notify_progress.emit(i*50)
sleep(1)
self.calculation_done.emit()
if __name__ == "__main__":
application = QtWidgets.QApplication(argv)
main_window = MainWindow()
main_window.show()
exit(application.exec_())