카테고리 없음

[PyQt5] 무작정 시작하기 (2) - 입력 & 버튼

허도치 2020. 7. 24. 18:08
서론

  지난 포스트에서는 간단하게 창을 두개 띄우는 것을 해보았다. 이번 포스트에서는 텍스트를 입력받고 버튼을 클릭하면 콘솔에 결과를 출력해주는 위젯을 구현할 것이다.

 

  코드를 깔끔하게 작성하고 재사용이 용이하도록 만들다보니 파이썬 입문자들에게는 다소 어려울 수 있으니 주의바란다.

 

 

 

1. 메인 위젯 작성
1-1. MyWidget.py
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# MyWidget.py
from functools import wraps
from PyQt5.QtWidgets import *
 
 
# 데코레이터
def addHBoxWithGrid(func):
  @wraps(func)
  def wrapper(self*args, **kwargs):
    row = kwargs.get("row"0)
    col = kwargs.get("col"0)
    rowspan = kwargs.get("rowspan"1)
    colspan = kwargs.get("colspan"1)
    
    # Sub Layout 생성
    # QHBoxLayout: Widget을 가로방향으로 나열
    hbox = QHBoxLayout()
    
    # hbox에 위젯 추가
    widgets = func(self*args, **kwargs)
    if isinstance( widgets, list ):
      for widget in widgets:
        hbox.addWidget(widget)
    else:
      hbox.addWidget(widgets)
    
    # Sub Layout을 Main Layout에 추가
    self.main_layout.addLayout(hbox, row, col, rowspan, colspan)
    
  return wrapper
  
 
# 메인 위젯
class MainWidget(QWidget):
  def __init__(self, parent=None):        
    super(MainWidget, self).__init__(parent)
    
    # 부모 윈도우 설정
    self.parent = parent
    
    # 입력 Widget 저장소
    self.form = {}
    
    # UI 렌더링
    self.render()
  
  # UI 렌더링
  def render(self):
    # Main Layout 생성
    # QGridLayout: Layout, Widget을 지정된 위치(row, col)에 나열.
    self.main_layout = QGridLayout(self)
    
    # Main Layout에 Sub Layout, Widget 추가
    self.addTextInput(
      label="이름:"
      name="username"
      row=0,
      col=0
    )
    self.addButton(
      label="이름 출력",
      row=0,
      col=1,
      target="username",
      onClick=self.handlePrintText
    )
    
    # Main Layout 설정
    self.setLayout(self.main_layout)
  
  # Text Input 위젯 추가
  @addHBoxWithGrid
  def addTextInput(self, label=None, name=None**kwargs):  
    w_label = QLabel(label)
    w_input = QLineEdit()
    
    if name is not None:
      self.form[name] = w_input
    
    return [ w_label, w_input ]
   
  # Button 위젯 추가
  @addHBoxWithGrid
  def addButton(self, label=None, target=None, onClick=None*args, **kwargs):  
    w_button = QPushButton(label)
    w_button.clicked.connect( onClick(target) )
    
    return w_button
  
  # 이벤트 핸들러
  def handlePrintText(self, target=None):
    def handle( res ):
      w_target = self.form.get(target, None)
      
      print( w_target.text() );
      
      w_target.setText("")
    
      return res
    return handle
 
cs

 

 

 

2. 메인 윈도우 작성
2-1. MainWindow.py
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
# MyWindow.py
from PyQt5.QtWidgets import QMainWindow, QDesktopWidget
from MyWidget import MainWidget
   
# 메인 윈도우
class MainWindow(QMainWindow):
  def __init__(self, title="Window"**kwargs):
    super(QMainWindow, self).__init__()
    
    # 상태값 설정
    self.title = title
    self.posX = int(kwargs.get("posX"0))
    self.posY = int(kwargs.get("posY"0))
    self.width = int(kwargs.get("width"300))
    self.height = int(kwargs.get("height"200))
    
    # UI 렌더링
    self.render()
    
  # UI 렌더링
  def render(self):
    self.init_window()
    self.init_widget()
    
  # 윈도우 설정
  def init_window(self):
    # 제목 설정
    self.setWindowTitle(self.title)
    
    # 크기 및 위치 설정
    self.setGeometry(self.posX, self.posY, self.width, self.height)    
    
    # 화면 가운데 정렬
    frame_geo = self.frameGeometry()
    desktop_center = QDesktopWidget().availableGeometry().center()
    frame_geo.moveCenter(desktop_center)
    self.move(frame_geo.topLeft())
 
  # 메인 위젯 설정
  def init_widget(self):
    self.main_widget = MainWidget(self)
    self.setCentralWidget(self.main_widget)
 
cs

 

 

 

3. 실행 파일 작성
3-1. app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# app.py
import sys
 
from PyQt5.QtWidgets import QApplication
from MyWindow import MainWindow
 
if __name__ == '__main__':  
  app = QApplication( sys.argv )
  win = MainWindow(
    title="메인 윈도우"
    posX=100, posY=400
    width=300, height=200
  )
  win.show()
  
  sys.exit( app.exec() )
cs

 

 

 

4. 실행
4-1. 스크립트 실행
1
python app.py
cs

 

 

4-2. 실행 결과

 

 

 

마치며

  - 처음에 간단하게 입력이랑 버튼 위젯을 추가하도록 만들었는데, 위젯이 많아질 때마다 같은 소스가 반복되었다. 그래서, 데코레이터로 묶어버렸는데 훨씬 깔끔하고 보기 좋아졌다.