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()