-
[PyQt5] 5. layoutPython/PyQt5 2021. 5. 19. 14:18반응형
레이아웃은 위젯들을 담아두는 틀입니다.
레이아웃을 잘 이용하면
자동으로 줄 맞춤이 되고,
좌표를 하드 코딩할 필요가 없어
유연한 GUI를 만들 수 있기 때문에,
무척 편합니다.하드 코딩은 데이터를 직접 코드 내에 넣어두는 것을 말합니다.
레이아웃을 사용하면 (좌표에 관련된) 숫자는 거의 사용하지 않습니다.최상위 위젯을 QMainWindow에서 QWidget으로 바꿨습니다.
이유는 마지막에...QVBoxLayout
QVBoxLayout이라는 클래스가 보입니다.
V는 Vertical(세로)에서 나왔다는 걸 알 수 있죠.QVBoxLayout 클래스로 layout 인스턴스를 만들어서
layout 인스턴스에 위젯들을 하나씩 addWidget 해 주었습니다.addWidget으로 상위 위젯에 add해주기 때문에
하위 위젯의 두 번째 인수로 상위 위젯(self 등)을
일일이 작성하지 않아도 됩니다.마무리로 self.setLayout(layout) 해 주었고요.
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget class MyWidget(QWidget): # QMainWindow 에서 QWidget 으로 바꿨습니다. def __init__(self): super().__init__() self.label = QLabel('label') self.button1 = QPushButton('button1') self.button1.clicked.connect(self.button1_clicked) self.button2 = QPushButton('button2') self.button2.clicked.connect(self.button2_clicked) layout = QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.button1) layout.addWidget(self.button2) self.setLayout(layout) def button1_clicked(self): self.label.setText('Clicked') def button2_clicked(self): self.label.setText('') app = QApplication([]) my_window = MyWidget() my_window.show() app.exec_()
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-1.py
결과는 다음과 같습니다.
줄이 잘 맞습니다.
이런 레이아웃들이 준비되어 있습니다.
- QVBoxLayout: 위젯들을 세로(위 -> 아래) 순서대로 배열합니다.
- QHBoxLayout: 위젯들을 가로(좌 -> 우) 순서대로 배열합니다.
- QGridLayout: 위젯들을 Grid의 지정된 Row, Column에 배열합니다.
- QFormLayout: 두 개의 위젯을 하나의 Row에 넣어줍니다. 폼 만들 때 편하겠죠?
QHBoxLayout
from PyQt5.QtWidgets import * class MyWindow(QWidget): def __init__(self): super().__init__() layout = QHBoxLayout() layout.addWidget(QPushButton('AAA')) layout.addWidget(QPushButton('BBB')) layout.addWidget(QPushButton('CCC')) self.setLayout(layout) app = QApplication([]) my_window = MyWindow() my_window.show() app.exec_()
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-2.py
QGridLayout
from PyQt5.QtWidgets import * class MyWindow(QWidget): def __init__(self): super().__init__() layout = QGridLayout() layout.addWidget(QPushButton('AAA'), 0, 0) layout.addWidget(QPushButton('BBB'), 0, 1) layout.addWidget(QPushButton('CCC'), 1, 1) self.setLayout(layout) app = QApplication([]) my_window = MyWindow() my_window.show() app.exec_()
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-3.py
QFormLayout
from PyQt5.QtWidgets import * class MyWindow(QWidget): def __init__(self): super().__init__() layout = QFormLayout() layout.addRow(QPushButton('AAA'), QPushButton('BBB')) layout.addRow(QPushButton('CCC'), QPushButton('DDD')) self.setLayout(layout) app = QApplication([]) my_window = MyWindow() my_window.show() app.exec_()
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-4.py
레이아웃(Layout)의 중첩
계산기를 만들어 보겠습니다.
layout을 위아래로 나눠서,
layout_upper에는 숫자 창(LineEdit)과 C 버튼을
layout_lower에는 나머지 버튼들을 넣었습니다.layout_upper는 위젯을 가로로 배열하는 QHBoxLayout을 사용했고,
layout_lower에는 위젯을 Grid로 배열을 해주는 QGridLayout을 사용했고,
전체적인 레이아웃(layout)에는 위젯을 세로로 배열하는 QVBoxLayout을 사용했습니다.layout을 상위 layout에 합칠 때는 addLayout을 씁니다.
from PyQt5.QtWidgets import * class MyWidget(QWidget): def __init__(self): super().__init__() self.line_edit = QLineEdit('0') self.button0 = QPushButton('0') self.button1 = QPushButton('1') self.button2 = QPushButton('2') self.button3 = QPushButton('3') self.button4 = QPushButton('4') self.button5 = QPushButton('5') self.button6 = QPushButton('6') self.button7 = QPushButton('7') self.button8 = QPushButton('8') self.button9 = QPushButton('9') self.button_add = QPushButton('+') self.button_sub = QPushButton('-') self.button_mul = QPushButton('*') self.button_div = QPushButton('/') self.button_clear = QPushButton('C') self.button_dot = QPushButton('.') self.button_equal = QPushButton('=') layout_upper = QHBoxLayout() layout_upper.addWidget(self.line_edit) layout_upper.addWidget(self.button_clear) layout_lower = QGridLayout() layout_lower.addWidget(self.button7, 0, 0) layout_lower.addWidget(self.button8, 0, 1) layout_lower.addWidget(self.button9, 0, 2) layout_lower.addWidget(self.button4, 1, 0) layout_lower.addWidget(self.button5, 1, 1) layout_lower.addWidget(self.button6, 1, 2) layout_lower.addWidget(self.button1, 2, 0) layout_lower.addWidget(self.button2, 2, 1) layout_lower.addWidget(self.button3, 2, 2) layout_lower.addWidget(self.button0, 3, 0) layout_lower.addWidget(self.button_dot, 3, 1) layout_lower.addWidget(self.button_equal, 3, 2) layout_lower.addWidget(self.button_sub, 0, 3) layout_lower.addWidget(self.button_div, 1, 3) layout_lower.addWidget(self.button_mul, 2, 3) layout_lower.addWidget(self.button_add, 3, 3) layout = QVBoxLayout() layout.addLayout(layout_upper) layout.addLayout(layout_lower) self.setLayout(layout) app = QApplication([]) my_window = MyWidget() my_window.show() app.exec_()
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-5.py
QMainWindow
QMainWindow를 Designer에서 보면
다른 최상위 위젯과 달리
지울 수 없는 QWidget 클래스의 centralwidget 객체(이름은 변경 가능)가 있습니다.그래서 코드를 직접 작성할 때는 다음과 같이 해주셔야 합니다.
QWidget의 객체를 만들고,
central_widget = QWidget()레이아웃을 작성하고
이 객체에 레이아웃을 등록하고
central_widget.setLayout(layout)마지막에는 setCentralWidget으로 그 위젯을 등록합니다.
self.setCentralWidget(central_widget)from PyQt5.QtWidgets import (QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget) class MyWidget(QMainWindow): def __init__(self): super().__init__() self.label = QLabel('label') self.button1 = QPushButton('button1') self.button1.clicked.connect(self.button1_clicked) self.button2 = QPushButton('button2') self.button2.clicked.connect(self.button2_clicked) central_widget = QWidget() layout = QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.button1) layout.addWidget(self.button2) central_widget.setLayout(layout) self.setCentralWidget(central_widget) def button1_clicked(self): self.label.setText('Clicked') def button2_clicked(self): self.label.setText('') app = QApplication([]) my_window = MyWidget() my_window.show() app.exec_()
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-6-1.py
아래 방식으로 작성해도 됩니다만...
전 위 방식이 더 편합니다.central_widget = QWidget() layout = QVBoxLayout(central_widget) # 이렇게 작성해도 됩니다만 layout.addWidget(self.label) layout.addWidget(self.button1) layout.addWidget(self.button2) self.setCentralWidget(central_widget)
https://github.com/pycrawling/pyqt5_study/blob/main/pyqt5_study_05-6.py
대규모의 GUI를 작성하거나
상태바와 메뉴가 필요할 때는
이런 구조가 편리하겠으나..간단한 구조의 GUI를 만들 때는
굳이 필요한 것 같지 않습니다.반응형