티스토리 뷰

이 글은 Codetorial의 PyQt5, 초보자를 위한 Python GUI 프로그래밍-PyQt5 등을 학습하는 과정을 기록한 것이다. 강좌 자체는 해당 사이트를 참고하기 바란다.

2019/12/03 - [Python/PyQt5] - PyQt5: 여러 위젯 사용하기 2-1(윈도우 디자인 편)

 

PyQt5: 여러 위젯 사용하기 2-1(윈도우 디자인 편)

이 글은 Codetorial의 PyQt5, 초보자를 위한 Python GUI 프로그래밍-PyQt5 등을 학습하는 과정을 기록한 것이다. 강좌 자체는 해당 사이트를 참고하기 바란다. 여러 위젯 사용하기 2-1(윈도우 디자인 편) 이번에는..

editor752.tistory.com

PyQt5: 여러 위젯 사용하기 2-2(시그널과 슬롯 연결 편)

앞선 포스팅에서 총 다섯 묶음의 위젯을(echo mode, validator, alignment, input mask, read-only)으로 QWidget에 배치하였다. 각 묶음의 콤보박스의 선택 내용에 따라 라인에디터 설정이 바뀌도록 코드를 추가해 보겠다. 콤보박스의 선택에서 발생하는 시그널인 actvatied()과 슬롯(여기에서는 사용자 메서드)를 연결하는 것이다.

연결된 시그널과 슬롯 1: Echo 묶음

콤보박스에서 라인에디터의 입력모드를 선택하면 그 선택에 따라 밑에 있는 라인에디터의 입력모드가 바뀐다.

1
2
3
4
5
6
7
8
9
10
11
12
13
      self.echo_cb.activated.connect(self.echo_changed)
 
 
    def echo_changed(self, index):
 
        if index == 0:
            self.echo_le.setEchoMode(QLineEdit.Normal)
        elif index == 1:
            self.echo_le.setEchoMode(QLineEdit.NoEcho)
        elif index == 2:
            self.echo_le.setEchoMode(QLineEdit.Password)
        elif index == 3:
            self.echo_le.setEchoMode(QLineEdit.PasswordEchoOnEdit)
cs

콤보박스에서 actvatied() 시그널이 발생하며 선택된 결과인 integer값이 메서드에 인자(여기에서는 index)로 전달된다. 이 integer값은 콤보박스 정의에서 addItem()으로 추가한 순서대로 0부터 시작하여 순차적으로 값이 늘어난다. 이 인덱스값에 따라 라인에디터의 입력모드가 Nomal, NoEcho, Password, PasswordEchoOnEdit로 바뀌게 된다. 이 setEchoMode()의 각 설정 모습은 아래의 포스팅을 참고하기 바란다.

2019/11/21 - [Python/PyQt5] - PyQt5: QLineEdit 사용하기 1

 

PyQt5: QLineEdit 사용하기 1

이 글은 Codetorial의 PyQt5, 초보자를 위한 Python GUI 프로그래밍-PyQt5 등을 학습하는 과정을 기록한 것이다. 강좌 자체는 해당 사이트를 참고하기 바란다. QLineEdit은 한 줄의 문자열을 입력하고 수정할 수..

editor752.tistory.com

2019/11/21 - [Python/PyQt5] - PyQt5: QLineEdit 사용하기 2

 

PyQt5: QLineEdit 사용하기 2

2019/11/21 - [Python/PyQt5] - PyQt5: QLineEdit 사용하기 1 PyQt5: QLineEdit 사용하기 2 이번에는 setEchoMode() 메서드에 대해 알아보자. setEchoMode() 는 아래와 같이 4가지 모드를 설정할 수 있으며 각 모..

editor752.tistory.com

연결된 시그널과 슬롯 2: validator 묶음

이번에는 콤보박스의 선택에 따라 라인에디터의 입력값의 범위를 지정된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        self.validator_cb.activated.connect(self.validator_changed)  
 
        
    def validator_changed(self, index):
 
        if index == 0:
            self.validator_le.setValidator(None)
        elif index == 1:
            self.validator_le.setValidator(QIntValidator(-9999))
        elif index == 2:
            double_validator = QDoubleValidator(-999.0999.02)
            double_validator.setNotation(QDoubleValidator.StandardNotation)
            self.validator_le.setValidator(double_validator)
 
        self.validator_le.clear()
cs

actvatied() 시그널이 넘겨준 인덱스값에 따라 라인에디터의 입력 범위에 제한이 발생한다. 인덱스가 0인 경우에는 문자나 숫자 모두 제한없이 입력이 가능하다. 인덱스가 1인 경우에는 -99 ~ 99 범위의 정수만 입력되며, 인덱스가 2인 경우에는 -999.0 ~ 999.0까지 실수(소수점 둘째자리까지 허용)만 입력된다. 입력 범위를 제한하기 위해 setValidator() 메서드와 QIntValidator, QDoubleValidator 등의 메서드가 사용되었다. 특히 실수값 제한을 위해서 double_validator를 사용하고 있는 모습을 눈여겨보자. 콤보박스의 선택에 바뀔 때마다 라인에디터를 비워주는 코드가 마지막에 추가되어 있다.

연결된 시그널과 슬롯 3: alignment 묶음

콤보박스의 선택에 따라 라인에디터의 정렬(왼쪽, 중앙, 오른쪽)이 바뀐다.

1
2
3
4
5
6
7
8
9
10
11
12
        self.alignment_cb.activated.connect(self.alignment_changed)
 
 
    def alignment_changed(self, index):
 
        if index == 0:
            self.alignment_le.setAlignment(Qt.AlignLeft)
        elif index == 1:
            self.alignment_le.setAlignment(Qt.AlignCenter)
        elif index == 2:
            self.alignment_le.setAlignment(Qt.AlignRight)
 
cs

actvatied() 시그널이 넘겨준 인덱스값에 따라 라인에디터에 입력된 문자열 등의 정렬 상태가 바뀐다. 인덱스가 0일 때는 왼쪽, 1일 때는 중앙, 2일 때는 오른쪽으로 정렬이 바뀐다. 정렬을 바꾸기 위해서 setAlignment() 메서드와 Qt.AlignLeft, Qt.AlignCenter, Qt.AlignRight 메서드가 사용되었다.

연결된 시그널과 슬롯 4: input_mask 묶음

콤보박스의 선택에 따라 라인에디터 입력 마스크가(전화번호, 연도, 라이센스 키) 바뀐다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        self.access_cb.activated.connect(self.input_mask_changed)
 
    def input_mask_changed(self, index):
 
        if index == 0:
            self.input_mask_le.setInputMask('')
        elif index == 1:
            self.input_mask_le.setInputMask('000-0000-0000')
        elif index == 2:
            self.input_mask_le.setInputMask('0000-00-00')
            self.input_mask_le.setText('20190410')
            self.input_mask_le.setCursorPosition(0)
        elif index == 3:
            self.input_mask_le.setInputMask('>AAAAA-AAAAA-AAAAA-AAAAA;#')
 
cs

actvatied() 시그널이 넘겨준 인덱스값에 따라 라인에디터의 입력 마스크가 바뀌게 된다. 인덱스가 0일 때는 별도의 마스크가 없으며, 1일 때는 "000-0000-0000" 형식의 전화번호 입력 마스크가 적용된다. 인덱스가 2일 때는 "2019-12-25"과 같은 날짜 형식의 입력 마스크가 적용되며, 3일 때는 "#"으로 자리가 표시되는 'ARDEL-EFSAQ-ADEAe-EF3AA'와 같은 라이센스 키 형태의 입력 마스크가 적용된다.
모든 입력 마스크는 QLineEdit의 메서드인 setInputMask() 메서드를 사용하여 구현되었다, 다만 인덱스가 2일 경우, 날짜 입력 형식 마스크를 선택하면 디폴트값으로 '20190410'를 표시해 주며, 커서가 첫 문자에 오도록 하는 코드가 추가되었다.

연결된 시그널과 슬롯 5: access_cb 묶음

콤보박스의 선택에 따라 라인에디터가 읽기 전용으로 바뀐다.

1
2
3
4
5
6
7
8
9
        self.input_mask_cb.activated.connect(self.input_mask_changed)
 
    def access_changed(self, index):
 
        if index == 0:
            self.access_le.setReadOnly(False)
        elif index == 1:
            self.access_le.setReadOnly(True)
 
cs

actvatied() 시그널이 넘겨준 인덱스값에 따라 라인에디터가 읽기 전용으로 바뀐다. 이때에는 라인에디터에 입력을 하거나 수정하는 것이 불가능하다. 인덱스값이 0일 때는 쓰기, 편집이 가능한 상태이며, 인덱스값이 1인 경우에는 읽기 모드로 고정된다. 이 옵션은 QLineEdit의 메서드인 setReadOnly()가 사용되었다.

여기까지 시그널과 슬롯이 연결되는 코드를 살펴보았다. 앞 포스팅의 코드에 해당 코드를 합치면 된다.

여기까지만 읽고 코드를 복붙했다면 아마도 에러가 발생했을 것이다. 여기서 짚고 넘어가야 할 부분이 있다. 위의 코드를 눈여겨봤다면 connect 관련 코드와 슬롯 선언에 해당하는 def의 들여쓰기에 차이가 있다는 사실이다. 위 코드는 이해를 돕기 위해 한 화면에 넣은 것일 뿐 전체 코드의 흐름에 맞는 방식은 아니다. connect 관련 코드는 ui 선언, 즉 앞의 전체 코드를 고려한다면 def initUI():에서 선언되어야 하며, 각 슬롯(echo_changed 등)은 def initUI()와 동등하게, 즉 같은 들여쓰기로 선언되어야 하는 것이다.

자 그렇다면 위 코드를 어떻게 넣어야 할까? 고민해 보기 바란다.

전체 코드는 아래에 첨부하였다.

실행 화면

전체 코드

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
 
 
class MyApp(QWidget):
 
    def __init__(self):
        super().__init__()
 
        self.initUI()
 
 
    def initUI(self):
 
        #  echo_group
        self.echo_group = QGroupBox('Echo')
        self.echo_label = QLabel('Mode: ')
 
        self.echo_cb = QComboBox()
        self.echo_cb.addItem('Normal')
        self.echo_cb.addItem('No Echo')
        self.echo_cb.addItem('Password')
        self.echo_cb.addItem('PasswordEchoOnEdit')
 
        self.echo_le = QLineEdit()
        self.echo_le.setPlaceholderText('Placeholder Text')
        self.echo_le.setFocus()
 
        #  validator_group
        self.validator_group = QGroupBox('validator')
        self.validator_label = QLabel('Type')
 
        self.validator_cb = QComboBox()
        self.validator_cb.addItem('No validator')
        self.validator_cb.addItem('Integer validator')
        self.validator_cb.addItem('Double validator')
 
        self.validator_le = QLineEdit()
        self.validator_le.setPlaceholderText('Placeholder Text')
 
        
        #  input_mask_group
        self.input_mask_group = QGroupBox('Input mask')
        self.input_mask_label = QLabel('Type: ')
 
        self.input_mask_cb = QComboBox()
        self.input_mask_cb.addItem('No mask')
        self.input_mask_cb.addItem('Phone number')
        self.input_mask_cb.addItem('ISO date')
        self.input_mask_cb.addItem('License key')
 
        self.input_mask_le = QLineEdit()
        self.input_mask_le.setPlaceholderText('Placeholder Text')
 
 
        #  alignment_group
        self.alignment_group = QGroupBox('Alignment')
        self.alignment_label = QLabel('Type: ')
 
        self.alignment_cb = QComboBox()
        self.alignment_cb.addItem('Left')
        self.alignment_cb.addItem('Centered')
        self.alignment_cb.addItem('Right')
 
        self.alignment_le = QLineEdit()
        self.alignment_le.setPlaceholderText('Placeholder Text')
 
 
        #  access_group
        self.access_group = QGroupBox('Access')
        self.access_label = QLabel('Type: ')
        self.access_cb = QComboBox()
        self.access_cb.addItem('False')
        self.access_cb.addItem('True')
        self.access_le = QLineEdit()
        self.access_le.setPlaceholderText('Placeholder Text')
 
 
        #  echo_layout  
        self.echo_layout = QGridLayout()
        self.echo_layout.addWidget(self.echo_label, 0 , 0)
        self.echo_layout.addWidget(self.echo_cb, 01)
        self.echo_layout.addWidget(self.echo_le, 1012)
        self.echo_group.setLayout(self.echo_layout)
 
 
        #  validator layout
        self.validator_layout = QGridLayout()
        self.validator_layout.addWidget(self.validator_label, 00)
        self.validator_layout.addWidget(self.validator_cb, 01)
        self.validator_layout.addWidget(self.validator_le, 1012)
        self.validator_group.setLayout(self.validator_layout)
 
 
        #  input_mask_layout
        self.input_mask_layout = QGridLayout()
        self.input_mask_layout.addWidget(self.input_mask_label, 00)
        self.input_mask_layout.addWidget(self.input_mask_cb, 01)
        self.input_mask_layout.addWidget(self.input_mask_le, 1012)
        self.input_mask_group.setLayout(self.input_mask_layout)
        
 
        #  Alignment_layout
        self.alignment_layout = QGridLayout()
        self.alignment_layout.addWidget(self.alignment_label, 00)
        self.alignment_layout.addWidget(self.alignment_cb, 01)
        self.alignment_layout.addWidget(self.alignment_le, 1012)
        self.alignment_group.setLayout(self.alignment_layout)
 
 
        #  access_layout
        self.access_layout = QGridLayout()
        self.access_layout.addWidget(self.access_label, 00)
        self.access_layout.addWidget(self.access_cb, 01)
        self.access_layout.addWidget(self.access_le, 1012)
        self.access_group.setLayout(self.access_layout)
 
        # layout
        self.layout = QGridLayout()
        self.layout.addWidget(self.echo_group, 00)
        self.layout.addWidget(self.validator_group, 10)
        self.layout.addWidget(self.input_mask_group, 01)
        self.layout.addWidget(self.alignment_group, 20)
        self.layout.addWidget(self.access_group, 11)
 
        self.setLayout(self.layout)
 
        self.setWindowTitle('Line Ediotr')
 
 
 
        # 연결된 시그널과 슬롯: Echo 묶음
        self.echo_cb.activated.connect(self.echo_changed)
        # 연결된 시그널과 슬롯: validator 묶음
        self.validator_cb.activated.connect(self.validator_changed)
        # 연결된 시그널과 슬롯: alignment 묶음
        self.alignment_cb.activated.connect(self.alignment_changed)
        # 연결된 시그널과 슬롯: input_mask 묶음
        self.input_mask_cb.activated.connect(self.input_mask_changed)
        # 연결된 시그널과 슬롯: access_cb 묶음
        self.access_cb.activated.connect(self.access_changed)
 
    def echo_changed(self, index):
 
        if index == 0:
            self.echo_le.setEchoMode(QLineEdit.Normal)
        elif index == 1:
            self.echo_le.setEchoMode(QLineEdit.NoEcho)
        elif index == 2:
            self.echo_le.setEchoMode(QLineEdit.Password)
        elif index == 3:
            self.echo_le.setEchoMode(QLineEdit.PasswordEchoOnEdit)
 
 
    def validator_changed(self, index):
 
        if index == 0:
            self.validator_le.setValidator(None)
        elif index == 1:
            self.validator_le.setValidator(QIntValidator(-9999))
        elif index == 2:
            double_validator = QDoubleValidator(-999.0999.02)
            double_validator.setNotation(QDoubleValidator.StandardNotation)
            self.validator_le.setValidator(double_validator)
 
        self.validator_le.clear()
 
 
    def alignment_changed(self, index):
 
        if index == 0:
            self.alignment_le.setAlignment(Qt.AlignLeft)
        elif index == 1:
            self.alignment_le.setAlignment(Qt.AlignCenter)
        elif index == 2:
            self.alignment_le.setAlignment(Qt.AlignRight)
 
 
    def input_mask_changed(self, index):
 
        if index == 0:
            self.input_mask_le.setInputMask('')
        elif index == 1:
            self.input_mask_le.setInputMask('000-0000-0000')
        elif index == 2:
            self.input_mask_le.setInputMask('0000-00-00')
            self.input_mask_le.setText('20190410')
            self.input_mask_le.setCursorPosition(0)
        elif index == 3:
            self.input_mask_le.setInputMask('>AAAAA-AAAAA-AAAAA-AAAAA;#')
        
 
    def access_changed(self, index):
 
        if index == 0:
            self.access_le.setReadOnly(False)
        elif index == 1:
            self.access_le.setReadOnly(True)
 
 
if __name__ == '__main__':
 
    app = QApplication(sys.argv)
    ex = MyApp()
    ex.show()
    sys.exit(app.exec_())
 
cs

 

134~143 라인의 위치를 눈여겨 보자.


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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
글 보관함
05-15 01:12