프로그래밍 언어/Python

[PyQt] 클릭한 곳에 원 그리기

sujo 2022. 9. 26. 10:00

[PyQ] 클릭한 곳에 원 그리기

 

개요

  • 마우스로 클릭한 곳에 원을 그리자!
  • 마우스가 클릭된 좌표를 알기 위해 "mousePressEvent" 사용
  • 원을 그리기 위해 "printEvent"를 정의
  • 아래는 사용된 ui 파일이다.
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?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>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="styleSheet">
   <string notr="true">background-color: rgb(175, 194, 255);</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>140</y>
      <width>711</width>
      <height>441</height>
     </rect>
    </property>
    <property name="autoFillBackground">
     <bool>false</bool>
    </property>
    <property name="styleSheet">
     <string notr="true">background-color: rgb(255, 255, 255);
border: 2px solid rgb(0, 0, 0);</string>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="scaledContents">
     <bool>false</bool>
    </property>
    <property name="border" stdset="0">
     <string/>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>220</x>
      <y>50</y>
      <width>331</width>
      <height>51</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <family>Agency FB</family>
      <pointsize>36</pointsize>
      <weight>75</weight>
      <bold>true</bold>
     </font>
    </property>
    <property name="text">
     <string>Click on the Board</string>
    </property>
    <property name="alignment">
     <set>Qt::AlignCenter</set>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>
 
cs

 

설명

기본적인 코드의 흐름은 아래와 같다.

  1. ui에 그림을 보여줄 보드(label)를 설정해준다. (ui 파일의 line 20)
  2. 그림을 그릴 이미지(image)를 보드의 크기만큼 선언해준다. (line 10 ~ line 11)
  3. 그린 원이 보드에 적용될 수 있도록, paintEvent를 정의한다. (line 14 ~ line 19)
  4. 마우스 클릭 이벤트(mousePressEvent)를 정의한다. (line 21 ~ line 22)
  5. 마우스가 있는 곳에서 원이 그려질 수 있도록 좌표를 수정한다. (line 25 ~ line 26)
  6.  이미지(image)에 수정된 좌표를 토대로 그림을 그린다. (line 28 ~ lien 31)

※ 구현 과정을 중점으로 한 것이기 때문에 기본적인 메서드에 대한 설명은 생략한다.

 

(여담)

이걸 구현하는데 생각보다 오랜 시간이 걸렸다.

pyqt에 대한 지식이 거의 없다시피 해서... ㅠㅠ

특히 paintEvent에 대해 이해하는게 좀 힘들었던 것 같다. 그렇다고 지금도 잘 아는 것 같진 않지만..ㅎ

그리고 그려지는 좌표가 창이 기준이 아니라 이미지 기준이라 좌표를 조정할 필요가 있었다.

 

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
 
class window_class(QMainWindow):
    def __init__(self):
        from PyQt5.uic import loadUi
        super(window_class, self).__init__()
        loadUi('../../ui/shape.ui'self)
        self.image = QImage(QSize(711441), QImage.Format_RGB32)
        self.image.fill(Qt.white)
 
    def paintEvent(self, e):
        from PyQt5 import QtGui
 
        canvas = QPainter(self)
        qpixmp = QtGui.QPixmap.fromImage(self.image)
        self.label.setPixmap(qpixmp)
 
    def mousePressEvent(self, e):
        self.drawCircle(e.x(), e.y())
 
    def drawCircle(self, x, y):
        x -= 50
        y -= 150
 
        qp = QPainter(self.image)
        qp.setPen(QPen(Qt.blue, 3))
        qp.drawEllipse(x, y, 2020)
        self.update()
 
import sys
app = QApplication(sys.argv)
window = window_class()
window.show()
app.exec()
cs

 

 

결과 화면