QThread

장승현·2023년 7월 25일
0

PyQt5

목록 보기
3/3
post-thumbnail

개요

프로세스(Process)는 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램을 의미한다. 프로세스는 스레드로 이루어져 있으며 여기서 스레드(Thread)는 프로세스에서 최소 작업 단위이다. 일반적으로 하나의 프로세스는 하나의 스레드를 가지고 작업을 수행한다. 하지만 하나의 프로세스 내에서 둘 이상의 스레드를 가지고 동시에 작업하는 것이 가능하며, 이를 멀티스레드(Multi Thread)라 한다.

소개

Python에서는 멀티스레드를 위해 스레드를 생성하는 여러 방법이 존재하는데, QThread가 이 중 하나이다. 즉, QThread는 Python 그 중에서도 PyQt에서 제공하는 스레드를 생성하는 클래스이다. UI를 제공하는 프로그램은 사용자에게 UI를 보여줌과 동시에 요구 기능을 수행해야 하기 때문에 최소 2개의 스레드를 사용해야 한다. 만약 스레드를 하나만 사용한다면, 요구 기능이 수행되는 동안 UI는 멈추게 돼 사용성에 문제가 생길 수 있다.

사용 예시

QThread를 이용하여 다음과 같이 경과 시간을 측정하는 간단한 UI를 만들어보겠다.

  • Python 코드
import os, sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5 import uic

base_dir = os.path.dirname(os.path.abspath(__file__)) 
form_class = uic.loadUiType(base_dir + "/test.ui")[0] # test.ui는 UI 파일

class MyThread(QThread):
    '''
    QThread를 상속받아 Timer 기능을 수행하는 클래스
    '''
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.is_running = False

    def run(self):
        '''
        QThread 시작
        '''
        self.time = 0
        self.is_running = True
        while self.is_running:
            if not self.is_running:
                break
            self.parent.set_time(self.time)
            self.msleep(1000)
            self.time += 1

    def stop(self):
        '''
        QThread 종료
        '''
        self.is_running = False

class WindowClass(QMainWindow, form_class):
    '''
    MainWindow Class
    '''
    def __init__(self) :
        super().__init__()
        self.initUi()

        self.pushButton.clicked.connect(self.push)

        self.mythread = MyThread(self)

    def initUi(self):
        '''
        UI 초기 세팅
        '''
        self.setupUi(self)
        self.set_time(0) # Timer를 0으로 세팅

    def push(self):
        '''
        사용자가 QPushButton을 눌렀을때 이벤트 처리 함수
        '''
        if not self.mythread.is_running:
            self.pushButton.setText('Stop')
            self.mythread.start() # Timer 기능을 수행하는 Thread 시작
        else:
            self.mythread.stop()
            self.mythread.terminate() # Timer 기능을 수행하는 Thread 종료
            self.pushButton.setText('Run')

    def set_time(self, time:int):
        '''
        Timer 시간 세팅하는 함수
        '''
        self.time_label.setText('Time: {} sec'.format(time))

if __name__ == "__main__" :
    app = QApplication(sys.argv) 
    myWindow = WindowClass() 
    myWindow.show()
    app.exec_()
  • UI 파일(test.ui)
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>161</width>
    <height>116</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Timer</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QLabel" name="time_label">
      <property name="text">
       <string/>
      </property>
      <property name="alignment">
       <set>Qt::AlignCenter</set>
      </property>
     </widget>
    </item>
    <item row="1" column="0">
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>Run</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>161</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>
profile
늦더라도 끝이 강한 내가 되자

1개의 댓글

comment-user-thumbnail
2023년 7월 25일

정보 감사합니다.

답글 달기