파이썬 예제 (랜덤 그리기)

들어가며

오늘은 파이썬의 랜덤과 쓰레드를 이용한 랜덤 그리기 예제입니다.

실행하면 아래와 같이 0.1초 주기로 원, 사각형을 무작위의 위치와 색으로 그려주는 방식으로 만들어 보았습니다.

[랜덤 그리기 실행모습]


소스코드

from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QColor, QBrush
from PyQt5.QtCore import Qt, QRect
from threading import Thread
import time
import random
import sys

QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)

class Shape:
    def __init__(self, type=0, r=0, g=0, b=0, a=0,rect=QRect()):
        self.type = type
        self.color = QColor(r, g, b, a)
        self.rect = rect


class Form(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('OCS Drawing')
        self.resize(600,600)

        self.shapes = []

        #Create thread
        self.bRun = True
        self.t = Thread(target = self.threadFunc)
        self.t.start()

    def paintEvent(self, e):
        qp = QPainter()
        qp.begin(self)

        for s in self.shapes:
            qp.setBrush(QBrush(s.color))
            if s.type==0:
                qp.drawRect(s.rect)
            else:
                qp.drawEllipse(s.rect)
        qp.end()

    def closeEvent(self, e):
        self.bRun = False

    def threadFunc(self):
        while self.bRun:
            type = random.randint(0, 1)
            r = random.randint(0, 255)
            g = random.randint(0, 255)
            b = random.randint(0, 255)
            a = random.randint(50,200)
            size = random.randint(10, 100)
            x = random.randint(0, self.rect().width() - size)
            y = random.randint(0, self.rect().height() - size)
            s = Shape(type, r, g, b, a, QRect(x, y, size, size))
            self.shapes.append(s)
            
            if len(self.shapes)>100:
                del(self.shapes[0])

            self.update()
            time.sleep(0.1)


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


[라인 1~7] 

코드작성에 필요한 모듈을 불러옵니다. PyQt5, random, threading 등.


[라인 11~15]

도형 클래스의 선언입니다. 그려지는 도형은 아래와 같은 속성(Attribute)을 같습니다.

  • 타입 : 0이면 사각형, 1이면 원

  • 색상 : R, G, B, A(투명도)

  • 위치 : QRectF Class 타입으로 저장되는 도형 위치

n개의 도형 클래스 객체를 쓰레드에서 생성, 리스트로 저장해 그려주는 방식입니다.


[라인 19~29]

Form 위젯(윈도우) 클래스의 생성자 함수입니다.

QWidget으로 부터 상속받은 클래스 이므로, super class(부모)의 생성자도 같이 호출합니다.

이어서 Shape class (도형)의 객체를 저장하기 위한 리스트를 생성하고, Thread class의 객체도 생성해 threadFunc() 라는 함수를 위젯이 생성될때 호출되도록 합니다.

 

[라인 31~41]

QWidget의 paintEvent() 함수를 재정의 합니다.

이 함수는 위젯을 새로 그려야 할 필요가 있을때마다 호출되며, 그 경우는 처음 위젯이 생성되거나 위젯이 가려졌다 새로그려지는 경우, 또는 위젯의 크기가 변경되는 경우입니다.

C++ MFC 를 사용해본 경험이 있다면 OnPaint(), OnDraw() 함수와 동일한 역할을 수행합니다.

새로 그림을 그려야 하므로, QPainter class의 객체 (qp)를 생성하고, begin(), end() 사이에 그림을 그리는 코드를 삽입하면 그림이 그려지게 됩니다.

실제 그림을 그리는 코드는 반복문 안에 구현되어 있으며 나중에 설명할 쓰레드에서 생성된 Shape 객체들을 순회하며 해당 도형의 타입, 색, 위치를 가져와 그림을 그리는 방식입니다.

[도형 그리기 방식]

[라인 43~44]

위젯을 닫을때 호출되는 함수이며, 다음에 설명할 쓰레드 함수에서 무한루프를 탈출하도록 합니다.


[라인 46~63]

위젯 실행시 생성되는 별도의 실행흐름(Thread)에 의해 호출되는 함수이며, 무한 루프를 돌며 아래 역할을 수행합니다.

  • 도형 타입, 색상, 위치, 크기 랜덤 설정

  • 임시 Shape 객체 생성 (s)

  • 도형 리스트에 도형 객체 추가
  • 도형 리스트 갯수 제한 (100개)

    • update() 함수로 위젯의 painterEvent() 강제 호출, 새로그림

    • sleep() 함수로 0.1초 휴식


    [라인 66~70]

    앱과 위젯을 생성하는 메인함수 구문입니다.

    Qt의 QWidget을 생성하기 위해, 메인 이벤트처리를 담당할 QApplicaton 객체를 생성하고 QWidget의 객체를 생성합니다.

     

    이상으로 모든 설명을 마칩니다. 감사합니다.

    댓글

    이 블로그의 인기 게시물

    Qt Designer 설치하기

    C++ 예제 (소켓 서버, 이미지, 파일전송)