본문 바로가기

PyQt GUI

PyQt GUI (9) : 텝을 이용하여 GUI를 알차게 꾸미기 - QTabWidget

728x90

윈도우에서 단축 아이콘 우클릭 -> 속성을 선택하면 나오는 단축 아이콘의 속성 창입니다. 이 속성창에는 다양한 정보가 출력이 되는데요, 하나의 창에서 다양한 정보를 띄우기 위해서 "탭"을 이용하고 있습니다. 화면 위에 있는 "일반", "바로가기", "호환성", "보안", "자세히", "이전 버전"을 선택할 수 있는 것을 탭이라고 합니다. 이렇게 탭을 만들면, 하나의 창에서 완전히 서로 다른 내용을 보여 줄 수 있다는 장점이 있습니다. 탭에 있는 내용을 서로 다른 창에 보여주려면 무려 6개의 창이 필요하지만, 탭을 활용해서 하나의 창으로 UI를 만들었습니다. 

 

이번 포스팅에서는 위와 같이 탭을 이용하여 UI를 풍성하게 하는 방법을 알아보겠습니다. 가장 기본적인 코드는 아래와 같습니다. 

import sys
from PyQt5.QtWidgets import *

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

    def init_ui(self):
        tab = QTabWidget()

        tab_1 = self.create_tab_1()
        tab_2 = self.create_tab_2()

        tab.addTab(tab_1, "tab_1")
        tab.addTab(tab_2, "tab_2")

        main_layout = QVBoxLayout()
        main_layout.addWidget(tab)

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

    def create_tab_1(self):
        formlayout = QFormLayout()
        name = QLineEdit()
        age = QSpinBox()
        formlayout.addRow("Name", name)
        formlayout.addRow("Age", age)

        widget = QWidget()
        widget.setLayout(formlayout)
        scroll_area = QScrollArea()
        scroll_area.setWidget(widget)
        scroll_area.setWidgetResizable(True)
        return scroll_area

    def create_tab_2(self):
        layout = QVBoxLayout()
        button = QPushButton("Button")
        layout.addWidget(button)

        widget = QWidget()
        widget.setLayout(layout)
        scroll_area = QScrollArea()
        scroll_area.setWidget(widget)
        scroll_area.setWidgetResizable(True)
        return scroll_area

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

이 코드를 실행하면 다음과 같이 두 개의 탭을 가진 UI가 생성됩니다. 

전체 코드에서 가장 핵심적인 부분은 TabWidget을 만들고, 이 TabWidget의 각 탭에 ScrollArea를 추가하는 부분입니다. 이 부분만 따로 보면, 

        tab = QTabWidget() # 탭 위젯 생성

        tab_1 = self.create_tab_1() #tab_1를 생성
        
        tab.addTab(tab_1, "tab_1") #탭 위젯에 tab_1를 추가
        
        main_layout = QVBoxLayout()
        main_layout.addWidget(tab)
        
    def create_tab_1(self): #실제 tab_1를 생성하는 부분, return 값은 ScrollArea
        formlayout = QFormLayout()
        name = QLineEdit()
        age = QSpinBox()
        formlayout.addRow("Name", name)
        formlayout.addRow("Age", age) # ScrollArea에 설정할 레이아웃을 생성

        widget = QWidget()
        widget.setLayout(formlayout) # 위젯을 생성하고 이 위젯에 레이아웃을 설정
        scroll_area = QScrollArea()  # ScrollArea 생성
        scroll_area.setWidget(widget) # ScrollArea에 위젯을 지정
        scroll_area.setWidgetResizable(True) #ScrollArea안에 위젯들의 크기가 변할 수 있도록 설정
        return scroll_area #생성한 Scroll Area를 return

입니다. 다소 복잡한 형태인데요, 작은 부분 부터 큰 부분으로 보면

 

(위젯 -> 이 부분은 항상 나옵니다) 레이아웃 -> 위젯 -> 스크롤에어리어 -> 탭위젯 (-> 메인레이아웃: 이 부분은 항상 나옵니다)

 

여기서 레이아웃 -> 위젯 -> 스크롤에러이러 부분은 약간 불필요한 방식이라고 생각될 수 있는데, 스크롤에어리어를 사용하지 않으면 레이아웃이 커지는 경우 레이아웃의 아랫 부분에 있는 위젯이 짤리는 불상사가 발생합니다. 

 

스크롤에어리어는 말 그대로 스크롤바를 이용하여 스크롤 할 수 있는 영역을 만들어 주는 위젯인데요, 이 스크롤에어리어 위젯에는 레이아웃을 설정할 수 없고, 위젯만을 설정할(setWidget) 수 있기에 우리가 원하는 레이아웃을 스크롤에러리어에 설정하기 위해서는 부득이 하게도 레이아웃 -> 위젯 -> 스크롤에어리어 방식을 이용할 수 밖에 없습니다. 

 

실제로 예를들어 보겠습니다. 보통은 그럴일이 없지만, 하나의 탭에 102개의 위젯을 만들어보겠습니다. 

    def create_tab_1(self):
        formlayout = QFormLayout()
        name = QLineEdit()
        age = QSpinBox()
        formlayout.addRow("Name", name)
        formlayout.addRow("Age", age)
        for index in range(100):
            formlayout.addRow("button_{}".format(index), QPushButton(str(index)))

        widget = QWidget()
        widget.setLayout(formlayout)
        #scroll_area = QScrollArea()
        #scroll_area.setWidget(widget)
        #scroll_area.setWidgetResizable(True)
        return widget

위 메인 코드의 create_tab_1 부분에서 ScrollArea를 사용하지 않고(주석처리 했습니다) 그냥 일반 Widget을 사용한다면,

와 같이 화면의 세로방향 전체에 위젯이 나오게 됩니다. 버튼 100개를 추가했는데, 모니터의 세로방향 길이의 한계상 31번 버튼까지 밖에 출력되지 않았습니다. 이러면 상당히 불편하겠죠. 다시 원래대로 ScrollArea를 사용한다면,

위와 같이 창의 크기로 지정한 400px x 400px 크기의 창이 뜨고, 탭의 오른쪽에 스크롤바가 생겼습니다. 이 스크롤바를 통해서 10번 버튼 부터 99번 버트까지를 접근할 수 있습니다. 꼭 탭위젯을 사용하는 경우가 아니라고 하더라도, 위젯의 갯수가 많아진다면 이처럼 스크롤에어리어 위젯을 이용해서 스크롤바를 추가해야합니다. 

 

스크롤에어리어가 준비되면, 이를 탭위젯에 추가하면 되는데요,

tab.addTab(tab_1, "tab_1")

와 같이 간단한 문법이면 됩니다. QFormLayout에서 addRow(라벨, 필드) 문법과 같이 탭위젯에서는 addTab(위젯, 이름)으로 추가 합니다. 각 탭에서는 레이아웃에다 원하는 위젯을 넣어서 원하는 화면을 꾸밀 수 있습니다. 

 

탭위젯에도 다양한 이벤트 기능이 있는데요, 그 중에서도 대표적인것은 선택한 탭이 바뀌었을 때, 몇 번째 탭으로 바뀌었는지를 전달하는 이벤트 입니다. 

        tab.currentChanged.connect(self.print_index)
    def print_index(self, tab):
        print(tab)

currentChanged.connect(함수) 를 이용하여 선택된 탭이 변경이 되면 함수를 호출하게 할 수 있습니다. 위 코드의 예시는 선택된 탭이 바뀔 때, 선택된 탭이 몇 번째 탭인지를 출력하는 간단한 예시입니다. 

 

728x90