본문 바로가기
카테고리 없음

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

by 허도치 2020. 7. 24.
서론

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

 

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

 

 

 

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. 실행 결과

 

 

 

마치며

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

댓글