Многопоточность в PyQT5, закрытие и рестарт потока

Рейтинг: 1Ответов: 0Опубликовано: 09.02.2023

У меня есть небольшое приложение на PyQT5. В нем таблица и кнопка "Считать". При нажатии на кнопку я запускаю в отдельном потоке запись данных из БД SQLite в таблицу в графическом интерфейсе. Одновременно с записью данных открывается диалоговое окно, которое показывает прогресс. Таблица заполняется построчно (!!за смену строк отвечает переменная i, это важно, далее проблема будет касаться именно этого момента!!), данные берутся из функции run() этого объекта:

class FillTableWidgetThread(QtCore.QObject):
    running = False
    new_table_row = QtCore.pyqtSignal(int, object)

    def run(self):
        i = 0
        self.total_events_count.emit(len(session.query(Event).all()))
        for event in session.query(Event).all():
            # print(i)
            list = [
                QTableWidgetItem(str(i+1)),
                QTableWidgetItem(str(event.date_time)),
                QTableWidgetItem(str(event.bku)),
                QTableWidgetItem(str(event.kl)),
                QTableWidgetItem(str(event.au)),
                QTableWidgetItem(str(event.channel)),
                QTableWidgetItem(str(event.event_code)),
                QTableWidgetItem(str(event.addit_param)),
                QTableWidgetItem(str(event.description)),
                QColor(codes_dictionary[event.event_code][1])
            ]
            self.new_table_row.emit(i, list)
            i += 1
        i = 0

и далее этой строчкой передаются в основной поток, где и происходит заполнение таблицы:

self.new_table_row.emit(i, list)

В целом код отрабатывает нормально, но, когда все данные считались и таблица заполнилась, я хочу, чтобы при повторном нажатии на кнопку "Считать" все данные из таблицы стирались и происходила повторная запись, начиная с первой строчки таблицы. Вот функция которая за это отвечает:

    def start_read(self):
        self.table.clearContents() # очищаем таблицу от старых данных
        self.table_thread.start() # запускаем поток записи данных в таблицу
        self.reading_progress_modal_dialog.show()
        self.reading_progress_modal_dialog.exec_()

Но этого не происходит, и таблица начинает заполняться с той же строки, где была остановлена запись повторным нажатием кнопки "Считать".

Переменная i объекта FillTableWidgetThread не сбрасывает свое значение в ноль, а запоминает. Отсюда вопрос, как после успешной загрузки закрыть поток и обновить значение переменной? Нужно ли при каждом нажатии на кнопку "Считать" создавать новый объект класса FillTableWidgetThread?

Ниже будет общий код программы (удалил из него лишнее, не относящееся к проблеме, чтобы проще читалось) и скрин самого окна.

class FillTableWidgetThread(QtCore.QObject):
    running = False
    new_table_row = QtCore.pyqtSignal(int, object)

    def run(self):
        i = 0
        self.total_events_count.emit(len(session.query(Event).all()))
        for event in session.query(Event).all():
            # print(i)
            list = [
                QTableWidgetItem(str(i+1)),
                QTableWidgetItem(str(event.date_time)),
                QTableWidgetItem(str(event.bku)),
                QTableWidgetItem(str(event.kl)),
                QTableWidgetItem(str(event.au)),
                QTableWidgetItem(str(event.channel)),
                QTableWidgetItem(str(event.event_code)),
                QTableWidgetItem(str(event.addit_param)),
                QTableWidgetItem(str(event.description)),
                QColor(codes_dictionary[event.event_code][1])
            ]
            self.new_table_row.emit(i, list)
            i += 1


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # конфигурация главного окна и центрального виджета
        self.central_widget = QWidget(self)
        self.setGeometry(50, 50, 1500, 800)
        self.setWindowTitle('Чтение БКУ')
        self.setCentralWidget(self.central_widget)
        self.layout_main_window = QVBoxLayout()
        self.central_widget.setLayout(self.layout_main_window)
        
        # конфигурация верхней панели инструментов
        self.btn_start_reading = QPushButton("Считать")
        self.btn_start_reading.clicked.connect(self.start_read)
        self.layout_toolbar.addWidget(self.btn_start_reading)
        self.layout_main_window.addLayout(self.layout_toolbar)

        # конфигурация таблицы
        self.layout_table = QHBoxLayout()
        self.table = QTableWidget()
        self.table.setColumnCount(9)
        self.table.setRowCount(13500)
        self.table.setHorizontalHeaderLabels(['№', 'Дата и время', 'БКУ', 'КЛ', 'АУ', 'Канал', 'Код события', 'Доп. параметр', 'Описание'])
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.horizontalHeader().setVisible(True)
        self.layout_table.addWidget(self.table)
        self.layout_main_window.addLayout(self.layout_table)

        # конфигурация диалоговых окон
        self.reading_progress_modal_dialog = ReadingProgressDialog()
        
        # конфигурация потоков
        self.table_thread = QtCore.QThread()
        self.fill_in_table_widget = FillTableWidgetThread()
        self.fill_in_table_widget.moveToThread(self.table_thread)
        self.fill_in_table_widget.new_table_row.connect(self.add_row_in_table)
        self.table_thread.started.connect(self.fill_in_table_widget.run)
        

    def start_read(self):
        self.table.clearContents() # очищаем таблицу от старых данных
        self.table_thread.start() # запускаем поток записи данных в таблицу
        self.reading_progress_modal_dialog.show()
        self.reading_progress_modal_dialog.exec_()
 
    # функция записи данных в таблицу
    @QtCore.pyqtSlot(int, object)   
    def add_row_in_table(self, i, list):
        self.table.setItem(i, 0, list[0])
        self.table.item(i, 0).setBackground(list[9])
        self.table.setItem(i, 1, list[1])
        self.table.item(i, 1).setBackground(list[9])
        self.table.setItem(i, 2, list[2])
        self.table.item(i, 2).setBackground(list[9])
        self.table.setItem(i, 3, list[3])
        self.table.item(i, 3).setBackground(list[9])
        self.table.setItem(i, 4, list[4])
        self.table.item(i, 4).setBackground(list[9])
        self.table.setItem(i, 5, list[5])
        self.table.item(i, 5).setBackground(list[9])
        self.table.setItem(i, 6, list[6])
        self.table.item(i, 6).setBackground(list[9])
        self.table.setItem(i, 7, list[7])
        self.table.item(i, 7).setBackground(list[9])
        self.table.setItem(i, 8, list[8])
        self.table.item(i, 8).setBackground(list[9])


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

введите сюда описание изображения

Ответы

Ответов пока нет.