서론
지난 포스트에서는 간단하게 창을 두개 띄우는 것을 해보았다. 이번 포스트에서는 텍스트를 입력받고 버튼을 클릭하면 콘솔에 결과를 출력해주는 위젯을 구현할 것이다.
코드를 깔끔하게 작성하고 재사용이 용이하도록 만들다보니 파이썬 입문자들에게는 다소 어려울 수 있으니 주의바란다.
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. 실행 결과
마치며
- 처음에 간단하게 입력이랑 버튼 위젯을 추가하도록 만들었는데, 위젯이 많아질 때마다 같은 소스가 반복되었다. 그래서, 데코레이터로 묶어버렸는데 훨씬 깔끔하고 보기 좋아졌다.
댓글