(PyQt6)2. 기본 위젯 소개
- 목차 글 : 2024-08-06-pyQt6 Index
- 이전 글 : PyQt6_1. 시작해보기
작성할 내용들
- 기본위젯들
- QWidgets
- QDialog
- QScrollArea
- QLabel
- QLineEdit
- QPushButton
- QScrollArea
- QSpinBox / QDoubleSpinBox
- Pyside6-uic + 코드로 짜기
PyQt6는 HTML처럼 반응형 UI짜기 어렵다. 정 필요하다면
resizeEvent
발생할 때마다 위젯의 폭과 높이를 고려하여 기준 길이보다 짧거나 길 때 레이아웃을 바꾸도록 코드를 짜야한다.
QtWidgets
드래그 앤 드롭으로 UI 짜기
드래그 앤 드롭 방식으로 UI짜기 위해서는 다음 단계를 따른다.
1. Pycharm의 프로젝트를 새로 생성한다.
- 이 때
virtualEnv
를 활성화해야 하는 것을 권장한다.- 추후
pyinstaller
로.exe
만들 때 불필요한 라이브러리로 인해 용량 증가를 방지 목적으로 사용. - 또,
pyside6-designer.exe
,pyside6-uic.exe
의 경로를 비교적 쉽게 접근할 수 있다.
- 추후
2. PySide6
을 실행한다. (Qt5버전은 PySide2
를 설치하면 된다.)
1
pip install PySide6
3. pyside6-designer.exe
실행
다음과 같이 프로젝트 내부에 Scripts 폴더가 생성될 건데 터미널에 다음 명령어를 치면 PySide6-designer.exe
를 실행시킬 수 있다.
1
2
# 보통 Scripts 폴더 내에 생성된다.
.\Scripts\pyside6-designer.exe
실행하면 아래와 같은 창이 뜨는데 MainWindow
나 Widget
으로 생성해주자.
4. 드래그 앤 드롭으로 구현
- 위젯을 놓고 우클릭>배치>원하는 레이아웃으로 배치하기
- ctr/cmd +
r
: 위젯 미리보기 실행
- 버튼 클릭, 값변화 등등의 이벤트/signal 관리하고 싶으면 F4 나 편집>시그널/슬롯 편집 으로 시그널/슬롯을 연결한다.
- 연결한 슬롯은
uic
로 변환 이후 파이썬 파일에 함수/메소드로 구현한다..gif
파일과 같이 했을 경우slot1
이름을 가진 함수/메소드에 연결된다.
5. 구현 이후
구현 다했으면 .ui
파일로 저장 후 다음 커맨드로 .ui
파일을 .py
로 치환해서 코드 짤 수 있게 만든다.
1
/Scripts/pyside6-uic.exe [저장한 ui파일이름].uic -o [저장할 파이썬 ui파일 이름].py
terminal로 매번 스크립트 실행하기 귀찮다면 Pycharm의 Setting을 건드리거나
bat
등의 스크립트 파일을 만들어서 실행하자. PyCharm Setting을 설정은 다음과 같이 한다.(위의 경우 mainUI.ui 파일의 이름으로 저장한 .ui파일을 mainUI.ui파일로 변환한다는 뜻이다.) 우클릭 후 External Tools에 위 이름으로 설정된 Tool을 선택하면 변환해준다.
기본 위젯들 살펴보기
Pyside6-designer.exe 실행하면 확인할 수 있듯이 pyqt에서는 아래 그림과 같은 위젯들을 사용할 수 있다. 주로 사용하는 것들 위주로 빨간 사각형으로 표시했고 그 중 일부만 소개할 예정이다.
Spacers
사용을 권장하지 않은 이유는QWidgets
상속 받은 위젯들은.show/hide()
,.setVisible
등으로 표시하거나 숨길 수 있는 반면,Spacer
들은 상기한 메소드를 사용해서 표시/숨김 기능을 구현할 수 없다. 차라리QWidget
의setSizePolicy
기능을 활용해서Spacer
기능을 대체하는 것이 훨씬 낫다.
QMainWindow, QWidget, QDialog
1
2
3
4
class firstapp(QWidget) :
def __init__(self):
super().__init__() # 파이썬 상속 class 초기화
- QMainWindow : Menubar이 달려있는 메인 창.
- QWidget : 가장 범용적으로 사용되는 위젯.
- Menubar나 Status Bar 등 없이 간단한 창 구현할 때 이걸로 프로그램을 만들어도 된다.
- 많은 위젯들이
QWidget
에서 상속되는 경우가 많고QWidget
안QWidget
을 구현할 수 있다.
- QDialog : 앱의 설정창, 입력창 등을 구현할 때 사용하는 위젯
- 예를 들어, QDialog에 내장된
.accept
,.reject
등을 활용하여 종료이벤트를 달리할 수 있다.
- 예를 들어, QDialog에 내장된
QLabel
span
태그 같이 텍스트 위주 위젯을 넣을 때 사용한다.- 폰트 스타일 변경할 때
Qlabel.setFont
와QtGui.QFont
를 사용한다.
1
2
3
4
#QLabel
label = QLabel("This is QLabel")
# Inter폰트, 14pt, font.weight, italic 여부
label.setFont(QFont("Inter", 14, QFont.Weight.Bold, False))
가끔 위젯의 기능을 잘 모를 때에는
ctrl/cmd
+click
으로 위젯의 메소드 및 플래그 등을 확일할 수 있다. vsc, pycharm 모두 지원하긴 하나 vsc는 한 번에 코드를 잘 보여주는 반면, pycharm은 structure 파악하는 데 좋다.
QLineEdit
- id, password같은 한 줄짜리 입력창을 만들 때 사용하는 위젯이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#QLineEdit
## 일반적인 경우
string_input = QLineEdit()
string_input.setPlaceholderText("아무 문자열 넣어도 입력이 가능합니다.")
## 실수형 LineEdit()real_num_input = QLineEdit()
real_num_input.setValidator(QDoubleValidator(self))
real_num_input.setPlaceholderText("실수 값만 입력이 됩니다.")
real_num_input.textChanged.connect(lambda x :
string_input.setText(str(real_num_input.text())))
## 비밀번호 받기
password_input = QLineEdit()
password_input.setPlaceholderText("password here")
password_input.setEchoMode(QLineEdit.EchoMode.Password) # PyQt6 문법
password_input.textEdited.connect(lambda x : print(password_input.text()))
자주 쓰는 메소드 위주로 소개해보겠다.
.setPlaceholderText
: QLineEdit가 비어있을 때 어떤 값을 넣어야 할 지 힌트를 주는 문구를 설정한다..setValidator
: 입력값의 타입을 제한한다.PyQt6.QIntValidator
: 정수형 문자열만 받는다.PyQt6.QDoubleValidator
: 실수형 문자열만 받는다.
.setEchoMode
: 입력 모드를 변경한다(기본값은None
)QLineEdit.EchoMode.Password
비밀번호처럼 입력값을 가린다.
.textChanged
(signal) : 값이 변경할 때마다.connect
된 함수를 실행한다..textEdited
(signal) : 값 변경이 완료되었을 때.connect
된 함수를 실행한다.- 참고로
.connect()
할 때, lambda 함수를 사용하면 첫 번째 인자가self
가 들어가기 때문에self
를 받아줄 인자x
를 선언해야 항수관련 에러가 발생하지 않는다.
- 참고로
QPushButton
클릭 버튼을 만드는 위젯이다.
1
2
3
#QPushbutton
btn = QPushButton("click!")
btn.clicked.connect(lambda x : print("Button is clicked"))
대부분의 경우, clicked
signal만 알아도 버튼의 기능을 구현할 수 있다. 다음 글에 이 QPushButton
에 클릭하는 효과를 추가하는 방법에 다룰 예정이다.
Q(Double)SpinBox
- QSpinBox : 정수형 스핀박스
- QDoubleSpinBox : 실수형 스핀박스
1
2
3
4
5
6
7
8
9
10
11
12
#QSpinbox
intspinbox = QSpinBox() # QSpinBox는 기본적으로 0 ~ 100 사이 범위를 가진다. step = 1
# 최대 범위를 1000으로
intspinbox.setMaximum(1000)
# 최소 범위를 50intspinbox.setSingleStep(5) # 버튼 클릭당 5씩 값 변화
intspinbox.setMinimum(50)
#QDoubleSpinbox
doublebox = QDoubleSpinBox()
doublebox.setMaximum(31.4135)
doublebox.setMinimum(-10)
doublebox.setSingleStep(0.2)
.setMaximum()
: 숫자 최대 영역.setMinimum()
: 숫자 최소 영역.setSingleStep()
: 버튼, 스크롤 등으로 값 증가/감소 단위.valueChanged
(signal) : 값이 바뀔 때.connect
함수를 실행함.
복잡한 계산하는 프로그램을 만들 경우
QSpinBox
에 스크롤로 인해 때문에 프리징을 유발할 수 있다. 아래코드처럼wheelEvent
끄거나QTimer
을 이용해서 입력값 변경하는데 약간의 지연을 주는 것도 좋은 방법이다.
1 2 value = QSpinBox() value.wheelEvent = lambda event : None
코드 전체 보기
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
# 이렇게 하나씩 호출해도 좋지만..
# from PyQt6.QtWidgets import QMainWindow, QWidget, QDialog, QLabel, ...
# 그냥 아래 코드로 퉁쳐도 된다.
from PyQt6.QtWidgets import *
from PyQt6.QtGui import QDoubleValidator, QFont
class firstapp(QWidget) :
def __init__(self):
super().__init__() # 파이썬 상속 class 초기화
self.init_layout() # 레이아웃 초기화
def init_layout(self):
layout = QVBoxLayout(self) #QVBoxLayout(parent = self)
# Scorll Area QScroll = QScrollArea()
QScroll.setWidgetResizable(True)
widget = QWidget()
QScroll.setWidget(widget)
main_layout = QVBoxLayout(widget)
layout.addWidget(QScroll)
#QLabel
label = QLabel("This is QLabel")
label.setFont(QFont("Inter", 14, QFont.Weight.Bold, False))
main_layout.addWidget(label)
#QLineEdit
## 일반적인 경우
string_input = QLineEdit()
string_input.setPlaceholderText("아무 문자열 넣어도 입력이 가능합니다.")
main_layout.addWidget(string_input)
## 실수형 LineEdit() real_num_input = QLineEdit()
real_num_input.setValidator(QDoubleValidator(self))
real_num_input.setPlaceholderText("실수 값만 입력이 됩니다.")
real_num_input.textChanged.connect(lambda x : string_input.setText(str(real_num_input.text())))
main_layout.addWidget(real_num_input)
## 비밀번호 받기
password_input = QLineEdit()
password_input.setPlaceholderText("password here")
password_input.setEchoMode(QLineEdit.EchoMode.Password) # PyQt6 문법
password_input.textEdited.connect(lambda x : print(password_input.text()))
main_layout.addWidget(password_input)
#QPushbutton
btn = QPushButton("click!")
btn.clicked.connect(lambda x : print("Button is clicked"))
main_layout.addWidget(btn)
#QSpinbox
intspinbox = QSpinBox() # QSpinBox는 기본적으로 0 ~ 100 사이 범위를 가진다. step = 1
intspinbox.setMaximum(1000) # 최대 범위를 1000으로
intspinbox.setMinimum(50) # 최소 범위를 50
intspinbox.setSingleStep(5) # 버튼 클릭당 5씩 값 변화
main_layout.addWidget(intspinbox)
#QDoubleSpinbox
doublebox = QDoubleSpinBox()
doublebox.setMaximum(31.4135)
doublebox.setMinimum(-10)
doublebox.setSingleStep(0.2)
main_layout.addWidget(doublebox)
# 만약 이 파일이 메인 실행파일이라면 아래 코드를 실행
if __name__ == "__main__" :
app = QApplication([]) # 보통은 sys.argv 값을 넣는다.
win = firstapp()
win.show()
app.exec()
잡다한 팁 모음
이벤트 수정하기
signal
의 경우 valuechanged.connect(function)
으로 연결할 수 있는데, method Event
(Reimplemented Protected Functions)의 경우 다음과 같이 재정의한다.
1
2
wid1 = QLabel("Double Click Test")
wid1.mouseDoubleClickEvent = lambda x : print(wid1.text())
- 다음 글 : 2024-09-03-PyQt6 UI 꾸미기