最近在练习PyQt时,突发奇想在qt中有没有滑动按钮,经过一顿搜索,最终找到一位大佬写的按钮类(原文点这里),但是我发现他在实际运用时,还是有一点问题,就是小球各种参数需要自己进行微调,才能调出一个适合的按钮,于是我在此基础上完善了参数需要微调的问题,并新增用户调节颜色接口,以及滑动时间接口,最后增加了程序主动触发按钮函数,这个函数详情在我的上一个文章里(点这里),让这个滑动按钮更加简便。
一、效果图
![](https://img-blog.csdnimg.cn/direct/8db4aeb72f5f42f8a4df607d4e15c0e3.gif)
二、效果图
# coding: utf-8
# @Author: 小杨大帅哥
from PyQt5.QtCore import QPoint, QCoreApplication, Qt, QRectF
from PyQt5.QtGui import QMouseEvent, QColor, QPainter
from PyQt5.QtWidgets import QAbstractButton
class SlidButton(QAbstractButton):
def __init__(self, *args,
# 滑动总时间, 单位: s
slip_time=.3,
# 按钮未滑动小圆颜色
inner_color=QColor(89, 89, 89),
# 按钮滑动后小圆颜色
checked_inner_color=QColor(255, 255, 255),
# 按钮未滑动背景颜色
outer_color=QColor(212, 212, 212),
# 按钮滑动后背景颜色
checked_outer_color=QColor(51, 153, 255)):
super(SlidButton, self).__init__(*args)
self.__offset = None
self.__beginning_offset = None
self.__innerMargin = None
self.__innerDiameter = None
# 总滑动时间
self.__slipTime = slip_time * 1000
# 是否选中标志位
self.__checked = False
# 定时器ID
self.__timeId = None
# 鼠标形状
self.setCursor(Qt.PointingHandCursor)
self.__innerColor = inner_color
self.__checkedInnerColor = checked_inner_color
self.__outerColor = outer_color
self.__checkedOuterColor = checked_outer_color
def resizeEvent(self, event):
super(SlidButton, self).resizeEvent(event)
# 内部圆直径, 一般设置比高度小一点就可以了
self.__innerDiameter = self.height() - self.height() // 8
# 内边距
self.__innerMargin = 0
# 初始时刻小球左边缘距离边框在x坐标的偏移量
self.__offset = (self.width() - self.__innerDiameter) // 20
self.__beginning_offset = self.__offset
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(Qt.NoPen)
# 开启抗锯齿
painter.setRenderHint(QPainter.Antialiasing)
# 根据不同的选中状态切换内外颜色
if self.__checked:
__innerColor = self.__checkedInnerColor
__outerColor = self.__checkedOuterColor
else:
__innerColor = self.__innerColor
__outerColor = self.__outerColor
# 画外部圆角矩形
painter.setBrush(__outerColor)
painter.drawRoundedRect(self.rect(), self.height() // 2, self.height() // 2)
# 画内部圆形
painter.setBrush(__innerColor)
painter.drawEllipse(QRectF(self.__offset,
(self.height() - self.__innerDiameter) // 2,
self.__innerDiameter,
self.__innerDiameter))
def timerEvent(self, event):
# 根据选中状态修改x坐标偏移值
if self.__checked:
self.__offset += 1
# 圆球的位置要保持在圆框范围之内偏移
if self.__offset >= (self.width() - self.__innerDiameter - self.__beginning_offset):
self.killTimer(self.__timeId)
else:
self.__offset -= 1
if self.__offset <= self.__beginning_offset:
self.killTimer(self.__timeId)
# 调用update,进行重绘
self.update()
def killTimer(self, __timeId):
# 删除定时器的同时,将timeId置为None
super(SlidButton, self).killTimer(__timeId)
self.__timeId = None
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.__checked = not self.__checked
self.toggled.emit(self.__checked)
if self.__timeId:
self.killTimer(self.__timeId)
self.__timeId = self.startTimer(self.__slipTime // (self.width() -
self.__innerDiameter - self.__beginning_offset))
def isChecked(self):
return self.__checked
def fake_clicked(self):
"""
程序模仿人为操作按下按钮
"""
QCoreApplication.postEvent(self,
QMouseEvent(QMouseEvent.MouseButtonRelease,
self.mapToGlobal(QPoint(0, 0)),
self.mapToGlobal(QPoint(0, 0)),
Qt.LeftButton,
Qt.LeftButton,
Qt.NoModifier))