如何在PyQt6控件中实现CSS :after伪类的按钮动效
PyQt6实现CSS :after伪类扫光按钮效果
Qt Style Sheet(QSS)本身不支持CSS的:after、:before伪类,你需要的扫光效果可以通过重写控件绘制方法+属性动画的方式实现,完整可运行代码如下:
from PyQt6.QtCore import QRect, Qt, QPropertyAnimation, pyqtProperty, QEasingCurve from PyQt6.QtGui import QEnterEvent, QPainter, QColor from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton class QButton(QPushButton): def __init__(self, parent=None): super().__init__(parent) self.setText("Welcome") # 扫光效果相关属性 self._sweep_offset = -75 # 扫光条水平偏移量 self.sweep_angle = 35 # 扫光条旋转角度 self.sweep_opacity = 0.8 # 扫光条透明度 # 初始化动画 self.sweep_anim = QPropertyAnimation(self, b"sweep_offset") self.sweep_anim.setDuration(1000) self.sweep_anim.setEasingCurve(QEasingCurve.Type.OutCubic) # 基础样式 self.setStyleSheet(""" QPushButton{ background-color: #2E3440; letter-spacing: 0.1em; font-size: 14px; font-weight: 400; text-decoration: none; color: #FFF; border: 4px solid #4C566A; box-shadow:0px 0px 0px 1px #4C566A inset; } QPushButton:hover{ border: 4px solid #666; background-color: #D8DEE9; box-shadow:0px 0px 0px 4px #EEE inset; letter-spacing: 0.13em; color: #2E3440; } """) self.setFlat(True) self.setCursor(Qt.CursorShape.PointingHandCursor) self.setGeometry(QRect(200, 200, 200, 50)) def setText(self, text: str): super().setText(text.upper()) # 定义扫光偏移属性,供动画调用 @pyqtProperty(int) def sweep_offset(self): return self._sweep_offset @sweep_offset.setter def sweep_offset(self, value): self._sweep_offset = value self.update() # 触发重绘 def paintEvent(self, event): # 先绘制按钮基础内容 super().paintEvent(event) # 绘制扫光条 painter = QPainter(self) painter.setRenderHint(QPainter.RenderHint.Antialiasing) painter.setClipRect(self.rect()) # 限制绘制区域在按钮内部 painter.setOpacity(self.sweep_opacity) # 旋转坐标系 painter.translate(self._sweep_offset, 0) painter.rotate(self.sweep_angle) # 绘制半透明白色矩形 painter.fillRect(QRect(0, -50, 50, 155), QColor(255, 255, 255)) painter.end() def enterEvent(self, event: QEnterEvent) -> None: super().enterEvent(event) # 启动扫光动画:从左到右扫过 self.sweep_anim.setStartValue(-75) self.sweep_anim.setEndValue(self.width() + 50) self.sweep_anim.start() def leaveEvent(self, event) -> None: super().leaveEvent(event) # 重置扫光位置 self.sweep_offset = -75 class Renderer: def __init__(self, main_window: QMainWindow) -> None: self.main_window = main_window def render(self): self.button = QButton(self.main_window) if __name__ == "__main__": app = QApplication([]) window = QMainWindow() window.resize(600, 400) renderer = Renderer(window) renderer.render() window.show() exit(app.exec())
核心实现逻辑说明
- 自定义动画属性:通过
pyqtProperty定义扫光条偏移属性,使用QPropertyAnimation驱动属性变化,复现CSS的transition动画效果,缓动曲线和时长与原CSS完全对齐 - 自定义绘制:重写
paintEvent方法,在按钮原有样式之上绘制斜切的半透明白色扫光条,通过setClipRect限制绘制区域不会超出按钮边界,对应原CSS中overflow: hidden的效果 - 样式复用:基础的按钮背景、边框、文字样式直接用QSS实现,hover状态的样式变化直接写在QSS的
:hover伪类中,不需要在事件中手动切换样式
内容的提问来源于stack exchange,提问作者BladeOfLightX
相关产品推荐
相关产品推荐

