You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide6实现椭圆扩散hover效果自定义按钮效果不符求助

核心问题

你的实现和目标效果差别的根源在几个逻辑写偏了:

  • 扩散椭圆的圆心写死成了按钮中心,目标效果是从鼠标进入按钮的落点开始往外扩散
  • 给按钮边框加了多余的padding缩放动效,目标效果里按钮本身大小、圆角全程不动,只有内部椭圆扩散
  • 文字颜色靠硬编码动画值阈值切换,和扩散进度不同步,过渡生硬
  • 椭圆最大半径写死成固定值75,按钮尺寸变了就会出现动画结束还盖不满的情况
修正方案

调整绘制逻辑和动画参数:

  1. 鼠标进入按钮时记录当前鼠标相对于控件的坐标,作为椭圆扩散的起点
  2. 删掉按钮轮廓的缩放逻辑,始终按控件原始尺寸绘制固定圆角的按钮基底,裁剪区域也固定为按钮形状
  3. 每次绘制时动态计算椭圆需要的最大半径:取扩散起点到按钮四个角的距离最大值,保证动画结束时椭圆能完全盖住整个按钮,适配任意按钮尺寸
  4. 调整绘制分层,不用硬编码颜色切换阈值,自然实现文字随扩散同步变色:
  • 最底层先画默认状态:浅灰圆角背景 + 黑色居中文字
  • 中间层在按钮形状裁剪范围内,画随动画进度放大的白色椭圆(hover状态的背景色)
  • 最上层同样在裁剪范围内,画浅色的居中文字,椭圆扩散到哪,浅色文字就覆盖到哪,和扩散进度完全同步
  1. 微调动画时长和缓动曲线,更贴近原效果的手感

修正后的完整可运行代码:

import sys
from math import hypot
from PySide6 import QtCore, QtWidgets, QtGui
from PySide6.QtWidgets import *
from PySide6.QtCore import *
from PySide6.QtGui import *

class Button19(QPushButton):
    Radius = 10
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 颜色配置:(默认色, hover色)
        self.bgColors = (QColor(Qt.lightGray), QColor(Qt.white))
        self.textColors = (QColor(Qt.black), QColor(Qt.lightGray))
        
        font = self.font()
        font.setBold(True)
        self.setFont(font)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setText("Button")

        # 动画配置
        self.hoverAnim = QVariantAnimation(self)
        self.hoverAnim.setStartValue(0.)
        self.hoverAnim.setEndValue(1.)
        self.hoverAnim.setEasingCurve(QEasingCurve.OutQuad)
        self.hoverAnim.setDuration(450)
        self.hoverAnim.valueChanged.connect(self.update)

        self._isHover = False
        self._hoverStartPos = QPointF()  # 记录鼠标进入的起点坐标

    def enterEvent(self, event):
        super().enterEvent(event)
        self._isHover = True
        self._hoverStartPos = event.position()  # 记录鼠标进入时的相对坐标
        self.hoverAnim.setDirection(QVariantAnimation.Forward)
        self.hoverAnim.start()

    def leaveEvent(self, event):
        super().leaveEvent(event)
        self._isHover = False
        self.hoverAnim.setDirection(QVariantAnimation.Backward)
        self.hoverAnim.start()

    def paintEvent(self, event):
        aniProgress = self.hoverAnim.currentValue()
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(Qt.NoPen)

        # 按钮固定轮廓,无缩放
        btnRect = QRectF(self.rect()).adjusted(5, 5, -5, -5)
        btnPath = QPainterPath()
        btnPath.addRoundedRect(btnRect, self.Radius, self.Radius)

        # 第一层:绘制默认状态 浅灰底+黑字
        painter.setBrush(self.bgColors[0])
        painter.drawPath(btnPath)
        painter.setPen(self.textColors[0])
        painter.drawText(btnRect, Qt.AlignCenter, self.text())

        # 计算扩散椭圆需要的最大半径:到四个角的最远距离
        maxRadius = max(
            hypot(self._hoverStartPos.x(), self._hoverStartPos.y()),
            hypot(self.width() - self._hoverStartPos.x(), self._hoverStartPos.y()),
            hypot(self._hoverStartPos.x(), self.height() - self._hoverStartPos.y()),
            hypot(self.width() - self._hoverStartPos.x(), self.height() - self._hoverStartPos.y())
        )
        currentRadius = maxRadius * aniProgress

        # 第二层:在按钮裁剪范围内绘制扩散白圆
        painter.save()
        painter.setClipPath(btnPath)
        painter.setBrush(self.bgColors[1])
        painter.drawEllipse(self._hoverStartPos, currentRadius, currentRadius)

        # 第三层:绘制hover状态的浅色文字,自动和圆扩散同步
        painter.setPen(self.textColors[1])
        painter.drawText(btnRect, Qt.AlignCenter, self.text())
        painter.restore()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    wind = QMainWindow()
    wind.setStyleSheet("QMainWindow{background-color:rgb(247,247,250)}")
    wind.resize(180, 80)
    wid = QWidget()
    lay = QHBoxLayout(wid)
    lay.setAlignment(Qt.AlignCenter)
    lay.addWidget(Button19())
    wind.setCentralWidget(wid)
    wind.show()
    sys.exit(app.exec())

补充说明:如果需要调整效果,直接改类里的颜色值、Radius(圆角大小)、动画时长/缓动曲线即可,扩散逻辑会自动适配任意按钮尺寸,不需要手动改半径参数。


内容的提问来源于stack exchange,提问作者Dream59

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:18:41