본문 바로가기

공부/Python

6. [Python] QThread , Thread 의 이해

반응형
import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QBoxLayout
from PyQt5 import QtCore
from PyQt5.QtCore import QObject

class Test(QObject):
    def __init__(self):
        super().__init__()
        self.cnt = 0
        self.stop_flag = False

    def start_test(self):
        while True:
            self.cnt += 1
            print('test1 = ', self.cnt)

            loop = QtCore.QEventLoop()
            QtCore.QTimer.singleShot(1000, loop.quit) #1000 ms
            loop.exec_()

            if self.stop_flag:
                self.stop_flag = False
                break

    def stop_test(self):
        self.stop_flag = True

class Test2(QObject):
    def __init__(self):
        super().__init__()
        self.cnt2 = 0
        # self.stop_flag = False

    def start_test2(self):
        while True:
            self.cnt2 += 1
            print('test2 = ', self.cnt2)

            loop = QtCore.QEventLoop()
            QtCore.QTimer.singleShot(1000, loop.quit) #1000 ms
            loop.exec_()

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.thread = QtCore.QThread()
        self.thread.start()
        self.test = Test()
        self.test.moveToThread(self.thread)

        self.thread2 = QtCore.QThread()
        self.thread2.start()
        self.test2 = Test2()
        self.test2.moveToThread(self.thread2)

        self.pb1 = QPushButton("start1")
        self.pb2 = QPushButton("stop")
        self.pb3 = QPushButton("start2")
        # self.test.start_test()

        form_lbx = QBoxLayout(QBoxLayout.TopToBottom, self)
        self.setLayout(form_lbx)

        form_lbx.addWidget(self.pb1)
        form_lbx.addWidget(self.pb2)
        form_lbx.addWidget(self.pb3)

        self.pb1.clicked.connect(self.test.start_test)
        self.pb2.clicked.connect(self.test.stop_test)
        self.pb3.clicked.connect(self.test2.start_test2)

if __name__ == "__main__":
    app = QApplication(sys.argv)

    form = MainWindow()
    form.show()
    app.exec_()

QObject 에서 moveToThread 를 통해서 Thread를 만들어 봤습니다.

이런식으로 Thread 설정하면 start1 버튼과 start2 버튼을 누르면 각각 할일을 합니다.

 

import sys

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QBoxLayout
from PyQt5 import QtCore
from PyQt5.QtCore import QObject

class Test(QObject):
    def __init__(self):
        super().__init__()
        self.cnt = 0
        self.stop_flag = False

    def start_test(self):
        while True:
            self.cnt += 1
            print('test1 = ', self.cnt)

            loop = QtCore.QEventLoop()
            QtCore.QTimer.singleShot(1000, loop.quit)
            loop.exec_()

            if self.stop_flag:
                self.stop_flag = False
                break

    def stop_test(self):
        self.stop_flag = True

class Test2(QObject):
    def __init__(self):
        super().__init__()
        self.cnt2 = 0

    def start_test2(self):
        while True:
            self.cnt2 += 1
            print('test2 = ', self.cnt2)

            loop = QtCore.QEventLoop()
            QtCore.QTimer.singleShot(1000, loop.quit)
            loop.exec_()


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        # self.thread = QtCore.QThread()
        # self.thread.start()
        self.test = Test()
        self.test2 = Test2()
        # self.test.moveToThread(self.thread)
        self.pb1 = QPushButton("start1")
        self.pb2 = QPushButton("stop1")
        self.pb3 = QPushButton("start2")
        # self.test.start_test()

        form_lbx = QBoxLayout(QBoxLayout.TopToBottom, self)
        self.setLayout(form_lbx)

        form_lbx.addWidget(self.pb1)
        form_lbx.addWidget(self.pb2)
        form_lbx.addWidget(self.pb3)

        self.pb1.clicked.connect(self.test.start_test)
        self.pb2.clicked.connect(self.test.stop_test)
        self.pb3.clicked.connect(self.test2.start_test2)

if __name__ == "__main__":
    app = QApplication(sys.argv)

    form = MainWindow()
    form.show()
    app.exec_()

위의 코드는 Thread와 다르게 2개의 Class로 만들었습니다.

이런식으로 class를 각자 만들어서 버튼을 누르면 test1이 끝나면 test2가 진행됩니다.

 

 

추가 내용!!

예제 1)

import sys
import time

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import *

class test_thread(QThread):
    def run(self):
        self.flag = False
        cnt = 0
        while True:
            cnt += 1
            print('test1 = {}', cnt)
            time.sleep(1)

            if self.flag:
                self.flag = False
                break

    def stop_test(self):
        self.flag = True


class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.Button_state = True
        self.pb_start.clicked.connect(self.click1_function)

        # thread setup
        self.test = test_thread()

    def click1_function(self):
        if self.Button_state:
            self.Button_state = False
            self.pb_start.setText('Stop')
            self.test.start()

        elif self.Button_state == False:
            self.Button_state = True
            self.pb_start.setText('start')
            self.test.stop_test()
        print('check')

    def setupUi(self, QMainWindow):
        self.resize(500, 500)
        self.centralwidget = QtWidgets.QWidget(QMainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pb_start = QtWidgets.QPushButton(self.centralwidget)
        self.pb_start.setGeometry(QtCore.QRect(100, 100, 100, 100))
        self.pb_start.setObjectName("pb_start")
        self.pb_start.setText("Start")
        QMainWindow.setCentralWidget(self.centralwidget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myApp = MyWindow()
    myApp.show()
    app.exec_()

예제 2) pyqtSignal 을 이용하여 데이터 전달

import sys
import time

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import *

class test_thread(QThread):
    th_val = pyqtSignal(int)

    def run(self):
        self.flag = False
        cnt = 0
        while True:
            cnt += 1
            print('test1 = {}', cnt)
            self.th_val.emit(cnt)
            time.sleep(1)

            if self.flag:
                self.flag = False
                break

    def stop_test(self):
        self.flag = True


class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.Button_state = True
        self.pb_start.clicked.connect(self.click1_function)

        # thread setup
        self.test = test_thread()
        self.test.th_val.connect(self.th_val_function)

    def click1_function(self):
        if self.Button_state:
            self.Button_state = False
            self.pb_start.setText('Stop')
            self.test.start()

        elif self.Button_state == False:
            self.Button_state = True
            self.pb_start.setText('start')
            self.test.stop_test()
        print('check')

    @pyqtSlot(int)
    def th_val_function(self, a):
        print('th_val = {}', a)


    def setupUi(self, QMainWindow):
        self.resize(500, 500)
        self.centralwidget = QtWidgets.QWidget(QMainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pb_start = QtWidgets.QPushButton(self.centralwidget)
        self.pb_start.setGeometry(QtCore.QRect(100, 100, 100, 100))
        self.pb_start.setObjectName("pb_start")
        self.pb_start.setText("Start")
        QMainWindow.setCentralWidget(self.centralwidget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myApp = MyWindow()
    myApp.show()
    app.exec_()

예제 3) thread에 변수 전달하기

import sys
import time

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import *

class test_thread(QThread):
    th_val = pyqtSignal(int)
    def __init__(self, args):
        super().__init__()
        self.flag = False
        self.data = args

    def run(self):
        # self.flag = False
        cnt = 0
        while True:
            cnt += 1
            print("test1 = {}".format(cnt))
            print('main_val={}'.format(self.data))
            self.th_val.emit(cnt)
            time.sleep(1)

            if self.flag:
                self.flag = False
                break

    def stop_test(self):
        self.flag = True


class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.Button_state = True
        self.main_val = []
        self.pb_start.clicked.connect(self.click1_function)

        # thread setup
        self.test = test_thread(args=self.main_val)
        self.test.th_val.connect(self.th_val_function)

    def click1_function(self):
        self.main_val.append(1)
        if self.Button_state:
            self.Button_state = False
            self.pb_start.setText('Stop')
            self.test.start()

        elif self.Button_state == False:
            self.Button_state = True
            self.pb_start.setText('start')
            self.test.stop_test()
        print('check')

    @pyqtSlot(int)
    def th_val_function(self, a):
        print('th_val = {}'.format(a))


    def setupUi(self, QMainWindow):
        self.resize(500, 500)
        self.centralwidget = QtWidgets.QWidget(QMainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pb_start = QtWidgets.QPushButton(self.centralwidget)
        self.pb_start.setGeometry(QtCore.QRect(100, 100, 100, 100))
        self.pb_start.setObjectName("pb_start")
        self.pb_start.setText("Start")
        QMainWindow.setCentralWidget(self.centralwidget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    myApp = MyWindow()
    myApp.show()
    app.exec_()

반응형

'공부 > Python' 카테고리의 다른 글

9. [Python] ipynb 파일 py로 변환하기  (0) 2020.01.03
7. [Python] 자료 구조 - list, tuple, dict  (1) 2019.12.20
4. [Python] QWaitCondition  (0) 2019.12.17
[Python] ** 의 쓰임  (0) 2019.12.17
[Python] Empty suite 에러 해결  (0) 2019.12.12