← Back to ToggleSwitch documentation
ToggleSwitch - Source Code¶
File: Distributed_Design_Optimizer/postprocess/widgets/ToggleSwitch.py
# Copyright (C) The DistributedDesignOptimizer Contributors
# Licensed under the GNU General Public License v3.0. See LICENSE file for details.
#
# Additional Request:
# We kindly request that any modifications or changes to the source code be
# shared with us by submitting them as pull requests to our GitHub repository.
# This request is not legally binding but is made in the spirit of
# collaboration and open-source development.
"""Custom toggle switch widget — a modern on/off slider control."""
from PySide6.QtWidgets import QWidget, QHBoxLayout, QLabel, QSizePolicy
from PySide6.QtCore import Signal, Qt, QRect, QPropertyAnimation, Property, QEasingCurve
from PySide6.QtGui import QPainter, QColor, QPen
from ..styles.Theme import PRIMARY
class _SwitchTrack(QWidget):
"""The sliding toggle track (no label)."""
toggled = Signal(bool)
def __init__(self, parent: QWidget | None = None) -> None:
"""Initialize the switch track widget.
Args:
parent: Optional parent widget.
"""
super().__init__(parent)
self.setFixedSize(40, 22)
self.setCursor(Qt.CursorShape.PointingHandCursor)
self._checked = False
self._thumb_x = 3.0
self._anim = QPropertyAnimation(self, b"thumb_x", self)
self._anim.setDuration(120)
self._anim.setEasingCurve(QEasingCurve.Type.InOutQuad)
def isChecked(self) -> bool:
"""Return whether the switch is in the on state.
Returns:
True if the switch is on, False otherwise.
"""
return self._checked
def setChecked(self, checked: bool) -> None:
"""Set the checked state and animate the thumb.
Args:
checked: ``True`` to turn on, ``False`` to turn off.
"""
if checked == self._checked:
return
self._checked = checked
target = 21.0 if checked else 3.0
self._anim.stop()
self._anim.setStartValue(self._thumb_x)
self._anim.setEndValue(target)
self._anim.start()
self.toggled.emit(checked)
def _get_thumb_x(self) -> float:
return self._thumb_x
def _set_thumb_x(self, val: float) -> None:
self._thumb_x = val
self.update()
thumb_x = Property(float, _get_thumb_x, _set_thumb_x)
def mousePressEvent(self, event) -> None:
"""Toggle the switch state on mouse press.
Args:
event: The mouse press event.
"""
if self.isEnabled():
self.setChecked(not self._checked)
def changeEvent(self, event) -> None:
"""Repaint when the enabled state changes.
Args:
event: The change event triggered by Qt.
"""
super().changeEvent(event)
if event.type() == event.Type.EnabledChange:
self.update()
def paintEvent(self, event) -> None:
"""Draw the track and sliding thumb.
Args:
event: The paint event triggered by Qt.
"""
p = QPainter()
if not p.begin(self):
return
p.setRenderHint(QPainter.RenderHint.Antialiasing)
disabled = not self.isEnabled()
# Track
if disabled:
track_color = QColor("#ddd")
elif self._checked:
track_color = QColor(PRIMARY)
else:
track_color = QColor("#ccc")
p.setPen(Qt.PenStyle.NoPen)
p.setBrush(track_color)
p.drawRoundedRect(QRect(0, 0, 40, 22), 11, 11)
# Thumb
p.setBrush(QColor("#f0f0f0") if disabled else QColor("white"))
p.setPen(QPen(QColor("#ccc") if disabled else QColor("#aaa"), 0.5))
p.drawEllipse(int(self._thumb_x), 3, 16, 16)
p.end()
class ToggleSwitch(QWidget):
"""A labelled toggle switch: [label] [=====O]."""
toggled = Signal(bool)
def __init__(self, label: str = "", parent: QWidget | None = None) -> None:
"""Initialize the labelled toggle switch.
Args:
label: Text label displayed beside the switch.
parent: Optional parent widget.
"""
super().__init__(parent)
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 2, 0, 2)
layout.setSpacing(6)
self._label = QLabel(label)
layout.addWidget(self._label)
self._switch = _SwitchTrack(self)
self._switch.toggled.connect(self.toggled.emit)
layout.addWidget(self._switch)
self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
def isChecked(self) -> bool:
"""Return whether the toggle is checked.
Returns:
True if the toggle is on, False otherwise.
"""
return self._switch.isChecked()
def setChecked(self, checked: bool) -> None:
"""Set the toggle checked state.
Args:
checked: ``True`` to turn on, ``False`` to turn off.
"""
self._switch.setChecked(checked)
def setToolTip(self, tip: str) -> None:
"""Apply the tooltip to the label and switch track.
Args:
tip: Tooltip text.
"""
super().setToolTip(tip)
self._label.setToolTip(tip)
self._switch.setToolTip(tip)