Profile picture

[Python / GUI] PySide6: QScrollArea 활용법

JaehyoJJAng2024년 08월 17일

개요

이번 주에 데이터를 추출하는 프로그램 외주를 1건 받게 되었는데,

의뢰 진행 중 고객이 추출한 데이터를 카드 형태로 프로그램에 출력되도록 요청을 하셨다.

이 과정에서 PySide6에 QScrollArea가 있다는 것을 알게 되었고, QScrollArea 활용법을 기록해보려고 한다.


목표

  • 매물 프로그램에서 크롤링된 데이터를 포토카드 형식으로 GUI에 표시하기

주요 기능

  • 중앙에 QScrollArea를 배치하여 스크롤 가능한 영역 구현
  • 각 매물을 이미지와 하메 카드 형식으로 표시
  • Qt Designer에서 디자인한 레이아웃을 그대로 사용

UI 디자인 (design.ui)

  • 실습이므로 QScrollArea만 배치하는 형식으로 진행

image
Qt Designer를 사용하여 애플리케이션의 UI를 디자인하자.

  • 메인 위젯: QWidget으로 설정
  • 레이아웃: 수평 레이아웃(QHBoxLayout)을 사용하여 좌우로 UI 배치
  • 좌측 영역: 카테고리나 필터링 옵션을 위한 위젯 배치(예: QListWidget, QPushButton ..)
  • 중앙 영역:
    • QScrollArea 위젯을 추가하고 이름을 scrollArea로 지정

코드 구현 (main.py)

from PySide6.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout
from PySide6.QtGui import QPixmap
from PySide6.QtUiTools import QUiLoader
from PySide6.QtCore import Qt
from layout_ui import Ui_Form  # 컴파일한 UI 지정
import os


class ItemCard(QWidget):
    def __init__(self, image_path, title, location, price, options, details):
        super().__init__()
        self.setFixedWidth(200)

        # 레이아웃 설정
        layout = QVBoxLayout()
        layout.setContentsMargins(5, 5, 5, 5)

        # 이미지 추가
        image_label = QLabel()
        pixmap = QPixmap(image_path).scaled(
            180, 180, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation
        )
        image_label.setPixmap(pixmap)
        layout.addWidget(image_label, alignment=Qt.AlignCenter)

        # 텍스트 정보 추가
        title_label = QLabel(f"<b>{title}</b>")
        location_label = QLabel(f"📍 {location}")
        price_label = QLabel(f"💰 {price}")
        options_label = QLabel(f"🛠 {options}")
        details_label = QLabel(f"{details}")

        # 텍스트 스타일 설정
        title_label.setAlignment(Qt.AlignCenter)
        location_label.setStyleSheet("color: gray;")
        price_label.setStyleSheet("color: green; font-weight: bold;")

        # 레이아웃에 위젯 추가
        layout.addWidget(title_label)
        layout.addWidget(location_label)
        layout.addWidget(price_label)
        layout.addWidget(options_label)
        layout.addWidget(details_label)

        self.setLayout(layout)


class MainWindow(QWidget, Ui_Form):
    def __init__(self):
        super().__init__()

        # UI 업데이트
        self.setupUi(self)

        # QScrollArea 영역 설정
        scroll_area = self.scrollArea
        scroll_content = QWidget()
        scroll_layout = QVBoxLayout(scroll_content)
        scroll_layout.setAlignment(Qt.AlignTop)

        # 샘플 데이터 추가
        sample_data = [
            {
                "image": "./sample.jpg",
                "title": f"매매_{i}",
                "location": f"서울시 {i}번지",
                "price": "1억",
                "options": "풀옵션",
                "details": "지하철역 근처, 편의시설 인접",
            }
            # 실제 데이터로 대체하세요
            for i in range(1, 5)
        ]

        for data in sample_data:
            card = ItemCard(
                image_path=data["image"],
                title=data["title"],
                location=data["location"],
                price=data["price"],
                options=data["options"],
                details=data["details"],
            )
            scroll_layout.addWidget(card)

        # scroll_area에 콘텐츠 설정
        scroll_area.setWidget(scroll_content)


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

코드 설명

  • ItemCard 클래스: 각 매물의 정보를 카드 형식으로 표시하는 위젯이다.
    • 이미지: QLabelQPixmap을 사용하여 이미지 표시
    • 텍스트 정보: QLabel을 사용하여 제목, 위치, 가격 등을 표시하고 아이콘이나 스타일을 적용
    • 레이아웃: QVBoxLayout으로 위젯들을 수직으로 정렬
  • MainWindow 클래스
    • scrollArea를 찾아 scroll_content를 설정
    • 샘플 데이터를 이용하여 ItemCard 인스턴스를 생성하고 scroll_layout에 추가
    • 샘플 데이터: 실제 크롤링한 데이터로 대체하여 사용하면 된다.

실행 결과

image


Loading script...