1. 학습 목표

더보기
  1.  QSS(= Qt 스타일시트) 를 사용해서 앱 전체에 공통 테마 적용하기
  2. QApplication 을 상속해서 테마 전용 Application 클래스 만들기
  3. QFile 로 .qss 파일 읽어서 setStyleSheet() 에 적용하기
  4. QMainWindow + QPushButton 에 hover / pressed 상태 스타일 입히기

 

2. 파일 구조 만들기

더보기
CustomThemeExample/
 ├─ custom_theme.qss      # [CSS/QSS] 테마 정의 파일
 │                        # - QMainWindow, QPushButton 등 위젯 스타일 정의
 │                        # - hover, pressed 같은 상태도 설정 가능
 │
 ├─ CustomTheme.py        # [Application 레벨 테마 시스템]
 │                        # - QApplication을 상속하여 CustomThemeApplication 클래스 생성
 │                        # - app 실행 시 .qss 테마 파일 자동 로드
 │                        # - setStyleSheet() 로 전체 애플리케이션 테마 적용
 │
 ├─ MainWindow.py         # [메인 UI 구성]
 │                        # - QMainWindow 상속
 │                        # - 버튼 등 UI 요소 배치
 │                        # - 테마는 CustomThemeApplication을 통해 자동 적용됨
 │
 └─ main.py               # [프로그램 진입점]
                          # - CustomThemeApplication 생성
                          # - MainWindow 실행 및 show()
                          # - 실제 앱을 실행하는 가장 상위 파일
  • CustomTheme.py : PySide6 코드 (CustomThemeApplication + MainWindow)
  • custom_theme.qss : QMainWindow, QPushButton에 적용할 스타일 정의

 

3. QSS 테마 파일(custom_theme.qss) 작성

: STEP 1

더보기
/* custom_theme.qss */

/* 1) 전체 메인 윈도우 배경 색 */
QMainWindow {
    background-color: #F0F0F0;
}

/* 2) 기본 버튼 스타일 */
QPushButton {
    background-color: #4CAF50;  /* 초록색 */
    color: white;               /* 글자 흰색 */
    border: none;               /* 기본 테두리 제거 */
    padding: 10px 20px;         /* 상하 10px, 좌우 20px 여백 */
}

/* 3) 마우스를 올렸을 때 (hover) */
QPushButton:hover {
    background-color: #45a049;  /* 조금 더 진한 초록색 */
}

/* 4) 버튼을 누르고 있을 때 (pressed 상태) */
QPushButton:pressed {
    background-color: #3e8e41;  /* 더 진한 초록색 */
}
  • QMainWindow { … }
    → 모든 QMainWindow에 적용
  • QPushButton { … }
    → 모든 QPushButton에 기본 스타일 적용
  • QPushButton:hover { … }
    → 마우스를 버튼 위에 올렸을 때 색상 변경
  • QPushButton:pressed { … }
    → 클릭하고 있을 때 색상 변경 (눌린 상태)

웹 CSS와 거의 비슷한 문법이지만, 태그 이름 대신 위젯 클래스 이름(QPushButton, QMainWindow 등)을 사용합니다.

 

4. CustomTheme 클래스 만들기

: STEP 2

더보기
# CustomTheme.py
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
from PySide6.QtCore import QFile
import sys


class CustomThemeApplication(QApplication):
    def __init__(self, theme_stylesheet_path):
        # QApplication 초기화
        super().__init__()

        # 생성자에서 바로 테마 로드
        self.load_theme_stylesheet(theme_stylesheet_path)

    def load_theme_stylesheet(self, theme_stylesheet_path):
        """QSS 테마 파일을 읽어서 애플리케이션 전체에 적용하는 함수"""

        style_file = QFile(theme_stylesheet_path)

        # 읽기 전용(ReadOnly) + 텍스트 모드(Text)로 오픈
        if style_file.open(QFile.ReadOnly | QFile.Text):
            # readAll() → QByteArray, str(..., encoding='utf-8') 으로 문자열로 변환
            style_sheet = str(style_file.readAll(), encoding='utf-8')

            # QApplication.setStyleSheet(...) 호출 → 앱 전체에 스타일 적용
            self.setStyleSheet(style_sheet)

            style_file.close()

이제 Python 코드에서, QApplication을 상속받은 CustomThemeApplication을 만들어
실행과 동시에 .qss 파일을 읽어서 스타일을 적용합니다.

 

 

class CustomThemeApplication(QApplication):
  • QApplication 상속→ 이 앱을 쓰는 한, 항상 테마가 자동으로 적용되도록 만들 수 있습니다.

 

 

app = CustomThemeApplication('custom_theme.qss')
  • 생성자에서 테마 경로 전달
    → .qss 파일만 바꿔 끼우면 다른 테마로 교체 가능

 

 

  • setStyleSheet() 를 QApplication 레벨에서 호출
    → 이 앱에서 생성되는 모든 위젯(QMainWindow, QPushButton 등)에 스타일이 적용됩니다.

 

5. MainWindow 만들기 (버튼 2개 배치)

: STEP 3

더보기
from PySide6.QtWidgets import QMainWindow, QPushButton


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # 윈도우 제목과 사이즈
        self.setWindowTitle("Custom Theme")
        self.resize(600, 400)

        # [버튼 1] "Click Me"
        button1 = QPushButton("Click Me", self)
        button1.setGeometry(100, 100, 200, 50)  # x, y, width, height

        # [버튼 2] "Click Two"
        button2 = QPushButton("Click Two", self)
        button2.setGeometry(100, 200, 300, 50)

 

6. main 진입점: 앱 실행 흐름

: STEP 4

더보기
import sys

from CustomTheme import CustomThemeApplication
from MainWindow import MainWindow

if __name__ == "__main__":
    # 1) 테마를 지원하는 Application 객체 생성 (QApplication 대신)
    app = CustomThemeApplication('custom_theme.qss')

    # 2) 메인 윈도우 생성 후 표시
    window = MainWindow()
    window.show()

    # 3) 이벤트 루프 시작
    sys.exit(app.exec())

 

  1. CustomThemeApplication('custom_theme.qss')
    → 생성자에서 load_theme_stylesheet() 호출
    → custom_theme.qss를 읽어서 app.setStyleSheet(...) 적용
  2. MainWindow()
    → 버튼 2개가 만들어지고, 이미 앱에 테마가 설정되어 있으므로
    자동으로 QSS에 정의된 스타일이 적용됨
  3. window.show() → app.exec()
    → 실제 GUI 실행, 테마가 입혀진 상태로 윈도우 등장

 

7.  추가 실습 과제

: (1) 특정 버튼에만 다른 스타일 적용하기

더보기

Python 코드에서:

button1.setObjectName("primaryButton")

 

QSS 파일에서

QPushButton#primaryButton {
    background-color: #2196F3;  /* 파란색 */
}

→ primaryButton에게만 다른 색 적용

 

 

 

 

* 확인할 사항

 

  • primaryButton에는 기본 배경색이 파란색(#2196F3) 으로 설정되고,
  • QPushButton:hover / QPushButton:pressed 가 일단 모든 버튼에 적용되긴 하지만,
  • Qt 스타일 시트의 매칭/우선순위 때문에 ID 선택자 쪽이 더 강해서
    hover/pressed 시에도 파란색이 유지되는 것처럼 보일 수 있습니다.
QPushButton#primaryButton {
    background-color: #2196F3;  /* 평소 파란색 */
}

/* primaryButton 전용 hover */
QPushButton#primaryButton:hover {
    background-color: #1E88E5;  /* 더 진한 파란색 */
}

/* primaryButton 전용 pressed */
QPushButton#primaryButton:pressed {
    background-color: #1565C0;  /* 더 더 진한 파란색 */
}

이렇게 하면:

  • 초록 버튼(button2)은 기존 hover/pressed 규칙 사용
  • 파란 버튼(button1)은 파란 계열로 hover/pressed 변화가 보입니다.

 


 

8.  추가 실습 과제

: (2) 다른 테마 파일 만들어서 교체해 보기

더보기
  • 테마 파일 2개
    • custom_theme_light.qss
    • custom_theme_dark.qss
  • 실행 방법
    • 기본: 라이트 테마로 실행
      python main.py
    • 다크 테마로 실행하는 방법
      python main.py dark

 

 

 

 

custom_theme_light.qss

 

/* custom_theme_light.qss */

/* 메인 윈도우 라이트 배경 */
QMainWindow {
    background-color: #F0F0F0;
}

/* 공통 버튼 스타일 (라이트 버전) */
QPushButton {
    background-color: #4CAF50;   /* 초록색 */
    color: white;                /* 글자 흰색 */
    border: none;                /* 기본 테두리 제거 */
    padding: 10px 20px;
}

/* hover */
QPushButton:hover {
    background-color: #45a049;
}

/* pressed */
QPushButton:pressed {
    background-color: #3e8e41;
}

 

 

 

 

custom_theme_dark.qss

/* custom_theme_dark.qss */

/* 메인 윈도우 다크 배경 */
QMainWindow {
    background-color: #303030;
}

/* 공통 버튼 스타일 (다크 버전) */
QPushButton {
    background-color: #555555;
    color: #FFFFFF;
    border: 1px solid #888888;
    padding: 10px 20px;
    border-radius: 4px;
}

/* hover */
QPushButton:hover {
    background-color: #666666;
}

/* pressed */
QPushButton:pressed {
    background-color: #444444;
}

 

 

 

 

CustomTheme.py

# CustomTheme.py
import os
import sys

from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QFile, QIODevice


class CustomThemeApplication(QApplication):
    def __init__(self, theme_name: str):
        """
        theme_name: 'light', 'dark' 중 하나라고 가정
        """
        super().__init__(sys.argv)

        # 현재 파일(CustomTheme.py)이 있는 디렉토리 기준으로 경로 계산
        base_dir = os.path.dirname(os.path.abspath(__file__))

        # theme_name 에 따라 사용할 qss 파일 결정
        if theme_name == "dark":
            qss_filename = "custom_theme_dark.qss"
        else:
            # 기본값: light
            qss_filename = "custom_theme_light.qss"

        self.qss_path = os.path.join(base_dir, qss_filename)

        # 실제 스타일 시트 로드
        self.load_theme_stylesheet(self.qss_path)

    def load_theme_stylesheet(self, qss_path: str):
        """
        QSS 테마 파일을 읽어서 애플리케이션 전체에 적용하는 함수
        """
        style_file = QFile(qss_path)

        if style_file.open(QIODevice.ReadOnly | QIODevice.Text):
            # QByteArray -> bytes -> str(utf-8 디코딩)
            style_sheet = bytes(style_file.readAll()).decode("utf-8")
            self.setStyleSheet(style_sheet)
            style_file.close()
        else:
            print("테마 파일을 열 수 없습니다:", qss_path)


 

 

 

MainWindow.py

# 동일

 

 

 

 

main.py

# main.py
import sys

from CustomTheme import CustomThemeApplication
from MainWindow import MainWindow


if __name__ == "__main__":
    # 1) 기본 테마: light
    theme_name = "light"

    # 2) 커맨드라인 인자 확인 (예: python main.py dark)
    if len(sys.argv) > 1:
        arg = sys.argv[1].lower()
        if arg in ("dark", "light"):
            theme_name = arg

    print(f"선택된 테마: {theme_name}")

    # 3) 선택된 테마 이름으로 Application 생성
    app = CustomThemeApplication(theme_name)

    # 4) 메인 윈도우 생성 및 표시
    window = MainWindow()
    window.show()

    # 5) 이벤트 루프 시작
    sys.exit(app.exec())

 

실행 후 체크

  • python main.py
    → 라이트 테마(밝은 배경 + 초록 버튼)
  • python main.py dark
    → 다크 테마(어두운 배경 + 회색 버튼)