129 lines
4.4 KiB
Python
129 lines
4.4 KiB
Python
from PySide6.QtCore import Qt, QRect, QPropertyAnimation, Property, Signal, QPoint
|
|
from PySide6.QtGui import QPainter, QColor, QFont
|
|
from PySide6.QtWidgets import QWidget
|
|
|
|
class ToggleSwitch(QWidget):
|
|
clicked = Signal(bool)
|
|
|
|
def __init__(self, parent=None, blue_theme=False):
|
|
super(ToggleSwitch, self).__init__(parent)
|
|
self.setFixedSize(50, 20)
|
|
self._checked = False
|
|
self._circle_color_checked = QColor('red')
|
|
self._circle_color_unchecked = QColor('gray')
|
|
self._background_color = QColor('white')
|
|
self._circle_pos = QPoint(0, 0)
|
|
self.animation = QPropertyAnimation(self, b"circle_pos")
|
|
self.animation.setDuration(250)
|
|
self.blue_theme = blue_theme
|
|
|
|
# 추가: 토글 상태에 따른 텍스트
|
|
self._on_text = "ON"
|
|
self._off_text = "OFF"
|
|
self._text_font = QFont("Arial", 10, QFont.Bold)
|
|
|
|
self._init_position()
|
|
|
|
@Property(QPoint)
|
|
def circle_pos(self):
|
|
return self._circle_pos
|
|
|
|
@circle_pos.setter
|
|
def circle_pos(self, pos):
|
|
self._circle_pos = pos
|
|
self.update()
|
|
|
|
def _init_position(self):
|
|
if self._checked:
|
|
self._circle_pos.setX(25)
|
|
else:
|
|
self._circle_pos.setX(0)
|
|
|
|
def mousePressEvent(self, event):
|
|
if event.button() == Qt.LeftButton:
|
|
self._checked = not self._checked
|
|
self.clicked.emit(self._checked)
|
|
self._update_animation()
|
|
self.update()
|
|
super(ToggleSwitch, self).mousePressEvent(event)
|
|
|
|
def _update_animation(self):
|
|
if self._checked:
|
|
self.animation.setStartValue(QPoint(0, 0))
|
|
self.animation.setEndValue(QPoint(25, 0))
|
|
else:
|
|
self.animation.setStartValue(QPoint(25, 0))
|
|
self.animation.setEndValue(QPoint(0, 0))
|
|
self.animation.start()
|
|
|
|
def paintEvent(self, event):
|
|
painter = QPainter(self)
|
|
painter.setRenderHint(QPainter.Antialiasing)
|
|
painter.setPen(Qt.NoPen)
|
|
|
|
# # 배경 색상 설정
|
|
# if self.isChecked():
|
|
# if self.blue_theme:
|
|
# self._background_color = QColor(0, 120, 215) # 활성화 상태: 진한 파란색
|
|
# else:
|
|
# self._background_color = QColor(33, 150, 243) # 활성화 상태: 파란색
|
|
# else:
|
|
# self._background_color = QColor(180, 180, 180) # 비활성화 상태: 회색
|
|
|
|
# 3D 효과를 위한 그림자 그리기
|
|
shadow_color = QColor(0, 0, 0, 50) # 반투명 검정색
|
|
painter.setPen(Qt.NoPen)
|
|
painter.setBrush(shadow_color)
|
|
painter.drawRoundedRect(2, 2, self.width(), self.height(), 13, 10)
|
|
|
|
# 배경 그리기
|
|
painter.setPen(Qt.NoPen)
|
|
painter.setBrush(self._background_color)
|
|
painter.drawRoundedRect(0, 0, self.width(), self.height(), 12, 10)
|
|
|
|
# 토글 원 그리기
|
|
circle_color = self._circle_color_checked if self._checked else self._circle_color_unchecked
|
|
painter.setBrush(circle_color)
|
|
painter.drawEllipse(self._circle_pos.x(), self._circle_pos.y(), 25, 20)
|
|
|
|
# 텍스트 그리기: 토글 상태에 따라 왼쪽(ON) 또는 오른쪽(OFF) 정렬
|
|
painter.setFont(self._text_font)
|
|
painter.setPen(QColor("black"))
|
|
if self._checked:
|
|
text = self._on_text
|
|
alignment = Qt.AlignLeft | Qt.AlignVCenter
|
|
else:
|
|
text = self._off_text
|
|
alignment = Qt.AlignRight | Qt.AlignVCenter
|
|
painter.drawText(self.rect(), alignment, text)
|
|
|
|
def setChecked(self, checked):
|
|
if self._checked != checked:
|
|
self._checked = checked
|
|
self._update_animation()
|
|
self.update()
|
|
|
|
def isChecked(self):
|
|
return self._checked
|
|
|
|
def setState(self, state):
|
|
"""ToggleSwitch의 상태를 설정합니다.
|
|
|
|
Args:
|
|
state (bool): True로 설정하면 스위치를 체크 상태로, False로 설정하면 언체크 상태로 변경합니다.
|
|
"""
|
|
if self._checked != state:
|
|
self._checked = state
|
|
self._update_animation()
|
|
self.clicked.emit(self._checked)
|
|
self.update()
|
|
|
|
# 텍스트를 설정하는 메서드들
|
|
def setOnText(self, text):
|
|
self._on_text = text
|
|
self.update()
|
|
|
|
def setOffText(self, text):
|
|
self._off_text = text
|
|
self.update()
|