from PySide6.QtWidgets import ( QAbstractButton, QApplication, QSizePolicy, QWidget, QVBoxLayout, ) from PySide6.QtCore import Qt, QRect, Signal from PySide6.QtGui import QPainter, QBrush class SwitchButton(QAbstractButton): # 开关切换信号 # 开: True, 关: False switched = Signal(bool) def __init__(self, parent=None): super().__init__(parent) self._checked = False self.setCursor(Qt.CursorShape.PointingHandCursor) # 颜色映射 self.color_keymap = { "slider": "#16ffff", "text": Qt.GlobalColor.white, "on_bg": "#008ee8", # 开的时候的背景颜色 "off_bg": "#001c83", # 关的时候的背景颜色 } self.clicked.connect(self.onClicked) self._init_style() # 新尺寸的样式表 self._init_size_policy() def _init_style(self): self.setStyleSheet( """ SwitchButton { font-family: "Microsoft YaHei"; font-size: 11px; color: white; border-radius: 9px; margin: 2px; min-width: 39px; max-width: 39px; min-height: 18px; max-height: 18px; } """ ) def _init_size_policy(self): self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) def paintEvent(self, event): # 1. 调整滑块间距 slider_space = 1 # 滑块与背景的间距(上下左右各1px) painter = QPainter(self) painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) try: # 2. 绘制背景 background_rect = self.rect() painter.setPen(Qt.PenStyle.NoPen) bg_color = ( self.color_keymap["on_bg"] if self._checked else self.color_keymap["off_bg"] ) painter.setBrush(QBrush(bg_color)) painter.drawRoundedRect( background_rect, self.height() / 2, self.height() / 2 ) # 3. 计算新滑块尺寸 slider_width = self.height() - slider_space * 2 # 4. 计算新滑块位置 if self._checked: slider_x = self.width() - slider_width - slider_space else: slider_x = slider_space slider_y = slider_space # 5. 绘制滑块 slider_rect = QRect(slider_x, slider_y, slider_width, slider_width) painter.setBrush(QBrush(self.color_keymap["slider"])) painter.drawEllipse(slider_rect) finally: painter.end() def onClicked(self): self._checked = not self._checked self.update() self.switched.emit(self._checked) def setChecked(self, checked: bool): self._checked = checked self.update() self.switched.emit(self._checked) def isChecked(self) -> bool: return self._checked # 测试示例 if __name__ == "__main__": import sys app = QApplication(sys.argv) test_window = QWidget() test_window.setWindowTitle("开关测试") test_window.resize(200, 100) layout = QVBoxLayout(test_window) layout.setContentsMargins(50, 30, 50, 30) switch = SwitchButton() switch.switched.connect( lambda state: print(f"开关状态:{'选中' if state else '未选中'}") ) layout.addWidget(switch) test_window.show() sys.exit(app.exec())