8.10 QSS 스타일 적용하기

1. 학습 목표
더보기


- QSS(= Qt 스타일시트) 를 사용해서 앱 전체에 공통 테마 적용하기
- QApplication 을 상속해서 테마 전용 Application 클래스 만들기
- QFile 로 .qss 파일 읽어서 setStyleSheet() 에 적용하기
- 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())
- CustomThemeApplication('custom_theme.qss')
→ 생성자에서 load_theme_stylesheet() 호출
→ custom_theme.qss를 읽어서 app.setStyleSheet(...) 적용 - MainWindow()
→ 버튼 2개가 만들어지고, 이미 앱에 테마가 설정되어 있으므로
자동으로 QSS에 정의된 스타일이 적용됨 - 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
→ 다크 테마(어두운 배경 + 회색 버튼)