反面教師あり学習

*/

(旧)反面教師あり学習

Negative Supervised Learning

QtPyでQThreadを使う例

概要

QtPyでQThreadを使う例です.

QtPyについて

eqseqs.hatenablog.com

つくったもの

ボタンを押すとバックグラウンドで何かが実行される. 処理の進捗や終了したタイミングSignalとしてGUI側に送信される. このアプリケーションではやっていないが処理結果の値を終了時に送信することもできる.

f:id:eqseqs:20210419160425g:plain

コード

# -*- coding: utf-8 -*-
import sys

from qtpy.QtWidgets import (
    QMainWindow, QApplication, QLabel, QWidget, QPushButton,
    QVBoxLayout
)
from qtpy.QtCore import QObject, Qt, QThread, QMutex, QMutexLocker
from qtpy.QtCore import Signal, Slot


class ExampleWorker(QThread):

    updated = Signal(str)
    finished = Signal()

    def __init__(self, **kwargs):
        super(ExampleWorker, self).__init__(**kwargs)

        self.mutex = QMutex()
        self.stopped = False

    def __del__(self):
        self.stop()

    def start(self):
        super(ExampleWorker, self).start()
        self.stopped = False

    def stop(self):
        with QMutexLocker(self.mutex):
            self.stopped = True

    def run(self):
        import time

        # --------- めっちゃ重たい処理 ---------
        cnt = 0
        while cnt < 20 and not self.stopped:
            self.updated.emit(str(cnt))
            cnt = cnt + 1
            time.sleep(0.25)
        # --------------------------------------

        self.finished.emit()


class MainWindow(QMainWindow):
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)

        # スレッドの準備

        self.worker = ExampleWorker()
        self.worker.updated.connect(self.on_worker_updated)
        self.worker.finished.connect(self.on_worker_finished)

        # UIの準備

        self.main_widget = QWidget(self)

        self.start_button = QPushButton('Start')
        self.start_button.clicked.connect(self.on_start_button_clicked)

        self.stop_button = QPushButton('Stop')
        self.stop_button.clicked.connect(self.on_stop_button_clicked)

        layout = QVBoxLayout()
        layout.addWidget(self.start_button)
        layout.addWidget(self.stop_button)

        self.main_widget.setLayout(layout)
        self.setCentralWidget(self.main_widget)
        self.resize(640, 480)

    def on_start_button_clicked(self):
        # スレッドが動いていないなら起動
        if not self.worker.isRunning():
            self.worker.start()

    def on_stop_button_clicked(self):
        self.worker.stop()

    @Slot(str)
    def on_worker_updated(self, s):
        print(s)

    @Slot()
    def on_worker_finished(self):
        print('おわり')


def main():
    app = QApplication(sys.argv)

    view = MainWindow()

    view.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()