Как вы подключаете сигнал из QMainWindow в QRunnable, используя PyQt5? - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь реализовать приложение Qt для чтения данных с инструмента и непрерывного построения графика с использованием PyQt5. У меня все работает, но в настоящее время я вызываю функцию в главном окне для проверки, должен ли рабочий QRunnable продолжать чтение или нет. Это кажется немного отрывочным, поскольку они работают в разных потоках. В Интернете довольно много ссылок о том, что QRunnables может отправлять и получать сигналы и что они предпочтительнее при использовании QThreadPool и QRunnable.

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

import sys
import time
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QRunnable, QThreadPool, QObject
from ui_stopwatch import Ui_MainWindow


class WorkerSignals(QObject):
    result = pyqtSignal(int)
    finished = pyqtSignal()


class Worker(QRunnable):

    def __init__(self, parent, count):
        super(Worker, self).__init__()
        self.signals = WorkerSignals()
        self.parent = parent
        self.count = count
        self.continue_counting = True

    @pyqtSlot()
    def run(self):
        while self.continue_counting:
            time.sleep(1)
            self.count += 1
            self.signals.result.emit(self.count)
            self.continue_counting = self.parent.get_counting_state()
        self.signals.finished.emit()


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.thread_pool = QThreadPool()
        self.bt_start.clicked.connect(self.start)
        self.bt_stop.clicked.connect(self.stop)
        self.counting_state = False
        self.count = 0

    def get_counting_state(self):
        return self.counting_state

    @pyqtSlot()
    def start(self):
        self.bt_start.setEnabled(False)
        self.counting_state = True
        worker = Worker(self, self.count)
        worker.signals.result.connect(self.update_time)
        worker.signals.finished.connect(self.enable_start)
        self.thread_pool.start(worker)
        self.bt_stop.setEnabled(True)

    @pyqtSlot()
    def stop(self):
        self.counting_state = False
        self.bt_stop.setEnabled(False)

    @pyqtSlot(int)
    def update_time(self, value):
        self.count = value
        self.label_output.setText(str(self.count))

    @pyqtSlot()
    def enable_start(self):
        self.bt_start.setEnabled(True)


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

Мой вопрос: как бы я изменил это вместо вызова функции get_counting_state() использовать сигнал из главного окна? Или мой подход с вызовом функции в порядке?

Я пропустил файл ui_stopwatch.py, который является просто файлом конструктора с двумя кнопками (bt_start и bt_stop) и меткой (label_output) ) но просто дайте мне знать, если вы хотите, чтобы я также добавил этот код.

...