본문 바로가기

PyQt GUI

PyQt GUI (3) : QFormLayout을 이용한 위젯 배치

728x90

https://www.youtube.com/watch?v=Tjq8TICkx3E

지난 포스팅 <PyQt GUI (2) : 레이아웃을 이용한 위젯 배치>에서 QVBoxLayout, QHBoxLayout, QGridLayout을 이용하여 위젯을 배치하는 것을 알아봤습니다. 이번 포스팅에서는 조금 특수한 형태의 레이아웃이라 할 수 있는 QFormLayout을 이용하여 위젯을 배치해 보도록 하겠습니다. 

 

인터넷의 회원 가입창에서 주로 볼 수 있는 자기 소개(혹은 개인 정보)를 입력하는 UI의 기본 코드는 아래와 같습니다.

import sys
from PyQt5.QtWidgets import *

class Main(QDialog):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        main_layout = QFormLayout()

        name_widget = QLineEdit()
        birthday_layout = QHBoxLayout()
        year_widget = QComboBox()
        month_widget = QComboBox()
        date_widget = QComboBox()

        birthday_layout.addWidget(year_widget)
        birthday_layout.addWidget(month_widget)
        birthday_layout.addWidget(date_widget)

        for year in range(1900, 2021):
            year_widget.addItem(str(year))
        for month in range(1, 13):
            month_widget.addItem(str(month))
        for date in range(1, 32):
            date_widget.addItem(str(date))

        address_layout = QVBoxLayout()
        address_1 = QComboBox()
        address_1.addItems(["Seoul", "Daejeon", "Daegu", "Busan"])
        address_2 = QLineEdit()
        address_layout.addWidget(address_1)
        address_layout.addWidget(address_2)

        email_layout = QHBoxLayout()
        email_id = QLineEdit()
        email_company = QLineEdit()
        email_combobox = QComboBox()
        email_combobox.addItems(["google.com", "naver.com", "daum.net"])
        email_layout.addWidget(email_id)
        email_layout.addWidget(QLabel("@"))
        email_layout.addWidget(email_company)
        email_layout.addWidget(email_combobox)

        phone_number_layout = QHBoxLayout()
        phone_number_layout.addWidget(QLineEdit())
        phone_number_layout.addWidget(QLabel("-"))
        phone_number_layout.addWidget(QLineEdit())
        phone_number_layout.addWidget(QLabel("-"))
        phone_number_layout.addWidget(QLineEdit())

        height_widget = QSpinBox()
        height_widget.setMaximum(250)

        personal_info = QCheckBox("Agree?")

        self_intro = QPlainTextEdit()

        save_cancel_layout = QHBoxLayout()
        save_button = QPushButton("Save")
        cancel_button = QPushButton("Cancel")
        save_cancel_layout.addWidget(save_button)
        save_cancel_layout.addWidget(cancel_button)

        main_layout.addRow("Name: ", name_widget)
        main_layout.addRow("Birthday: ", birthday_layout)
        main_layout.addRow("Address: ", address_layout)
        main_layout.addRow("E-mail: ", email_layout)
        main_layout.addRow("Phone Number: ", phone_number_layout)
        main_layout.addRow("Height(cm): ", height_widget)
        main_layout.addRow("Personal Information Share: ", personal_info)
        main_layout.addRow("Self Introduction: ", self_intro)
        main_layout.addRow("", save_cancel_layout)

        self.setLayout(main_layout)
        self.resize(500, 500)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Main()
    sys.exit(app.exec_())

코드의 앞 부분과 뒷 부분은 이전 포스팅의 코드와 같고, 실제로 다른 부분은 위젯을 생성하고 배치하는 unit_ui 메서드 부분입니다. 이 코드를 실행하면, 

와 같은 UI를 얻을 수 있습니다. 앞서 언급한 바와 같이 자기 소개를 하는 UI인데요, 이 UI와 같이 

 

질문 : 대답

 

이 계속 반복되는 형식의 위젯 배치가 필요할 때는 질문에 해당하는 위젯과 대답에 해당하는 위젯을 QHBoxLayout으로 묶어서 하나의 레이아웃을 만들고, 이 레이아웃을 QVBoxLayout으로 배치할 수 도 있지만, 위 예시와 같이 "질문 : 대답" 형식의 위젯 배치를 최적으로 하기 위해 마련된 QFormLayout을 사용하면 더 쉽고 이쁘게 위젯을 배치할 수 있습니다. 

 

QFormLayout의 "질문" 부분에 해당하는 것은 라벨(label)이라고 하고, "대답"에 해당하는 것은 필드(field)라고 합니다. 라벨과 필드에 들어갈 위젯들을 생성한 이후에, 

 

addRow(라벨, 필드)

 

와 같은 문법을 활용하여 폼-레이아웃에 위에서 부터 순서대로 한 줄 씩 위젯을 배치할 수 있습니다.

 

라벨 부분에는 주로 QLabel이 이용됩니다. 이 경우에는 QLabel를 만들 필요는 없고 그냥 str (" 문자 ") 만 입력 해 주어도 됩니다. 

        main_layout = QFormLayout() # QFormLayout 생성
        
        name_widget = QLineEdit()   # field에 들어갈 위젯 생성 : QLineEdit
        main_layout.addRow("Name: ", name_widget) # 앞에서 생성한 위젯을 main_layout에 추가
                                                  # label은 단순한 str 이므로 "Name :"와 같이
                                                  # 그냥 str을 그대로 입력

위 코드는 이름 정보를 입력하기 위해 "Name :" 이라는 라벨과 QLineEdit 위젯 필드를 추가한 것 입니다. 위 예시 코드에서는 다양한 위젯을 이용했는데요, 원하는 대로 위젯을 만들고 위 과정을 반복하기만 하면 됩니다. 

 

필드 부분에는 위젯 뿐 아니라 레이아웃도 입력이 가능합니다. 예를들어서,

        phone_number_layout = QHBoxLayout() # 레이아웃 생성
        phone_number_layout.addWidget(QLineEdit()) #레이아웃에 위젯 배치
        phone_number_layout.addWidget(QLabel("-"))
        phone_number_layout.addWidget(QLineEdit())
        phone_number_layout.addWidget(QLabel("-"))
        phone_number_layout.addWidget(QLineEdit())
        
        main_layout.addRow("Phone Number: ", phone_number_layout) #레이아웃을 필드로 추가

와 같이 전화 번호를 세 부분으로 구분하여 입력 받는 창을 생성해야 하는데, 이 경우에는 숫자를 입력하는 위젯과 "-"를 표현하는 위젯을 하나의 QHBoxLayout을 이용하여 가로로 한줄로 배치하고, 이렇게 생성된 레이아웃을 메인 레이아웃에 필드로 추가한 것 입니다. 

 

위 UI의 마지막 부분에는 Save, Cancel 버튼이 있는데, 이 Save, Cancel 버튼에는 라벨 값이 특별히 필요가 없습니다. 이 경우에는 라벨 값을 그냥 ""로 해도 됩니다. 

728x90