QAntAbstractButton.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. //
  2. // Created by Louis on 25-4-1.
  3. //
  4. #include "QAntAbstractButton.h"
  5. QAntAbstractButton::QAntAbstractButton(QWidget *parent) : QWidget(parent) {
  6. setAttribute(Qt::WA_Hover);
  7. // // 设置布局方案
  8. setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
  9. setCursor(Qt::PointingHandCursor);
  10. setAttribute(Qt::WA_TranslucentBackground);
  11. setStyleSheet("QWidget { border: none; background: transparent; }");
  12. // setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
  13. // 创建阴影效果
  14. m_shadowEffect = new QGraphicsDropShadowEffect(this);
  15. m_shadowEffect->setBlurRadius(0);
  16. m_shadowEffect->setColor(Qt::transparent);
  17. m_shadowEffect->setOffset(0, 0);
  18. setGraphicsEffect(m_shadowEffect);
  19. // 创建动画组
  20. m_animationGroup = new QParallelAnimationGroup(this);
  21. // 创建模糊半径动画
  22. QPropertyAnimation* blurAnimation = new QPropertyAnimation(m_shadowEffect, "blurRadius", this);
  23. blurAnimation->setDuration(300);
  24. blurAnimation->setStartValue(0);
  25. blurAnimation->setEndValue(25);
  26. blurAnimation->setEasingCurve(QEasingCurve::OutQuad);
  27. m_animationGroup->addAnimation(blurAnimation);
  28. // 创建颜色动画
  29. QPropertyAnimation* colorAnimation = new QPropertyAnimation(m_shadowEffect, "color", this);
  30. colorAnimation->setDuration(300);
  31. colorAnimation->setEasingCurve(QEasingCurve::OutQuad);
  32. m_animationGroup->addAnimation(colorAnimation);
  33. connect(m_animationGroup, &QParallelAnimationGroup::finished, this, [this]() {
  34. m_shadowEffect->setColor(Qt::transparent);
  35. m_shadowEffect->setBlurRadius(0);
  36. });
  37. }
  38. QAntAbstractButton::~QAntAbstractButton() {
  39. if (m_animationGroup) {
  40. delete m_animationGroup;
  41. m_animationGroup = nullptr;
  42. }
  43. if (m_shadowEffect) {
  44. delete m_shadowEffect;
  45. m_shadowEffect = nullptr;
  46. }
  47. }
  48. QString QAntAbstractButton::text() const {
  49. return m_text;
  50. }
  51. void QAntAbstractButton::setText(const QString &text) {
  52. if (text != m_text) {
  53. m_text = text;
  54. update();
  55. emit textChanged(text);
  56. }
  57. }
  58. QIcon QAntAbstractButton::icon() const {
  59. return m_icon;
  60. }
  61. void QAntAbstractButton::setIcon(const QIcon &icon) {
  62. if (icon.cacheKey() != m_icon.cacheKey()) {
  63. m_icon = icon;
  64. update();
  65. emit iconChanged(icon);
  66. }
  67. }
  68. QSize QAntAbstractButton::iconSize() const {
  69. return m_iconSize;
  70. }
  71. void QAntAbstractButton::setIconSize(const QSize &size) {
  72. if (m_iconSize != size) {
  73. m_iconSize = size;
  74. updateGeometry();
  75. update();
  76. }
  77. }
  78. QMargins QAntAbstractButton::padding() const {
  79. return m_padding;
  80. }
  81. void QAntAbstractButton::setPadding(const QMargins &margins) {
  82. if (m_padding != margins) {
  83. m_padding = margins;
  84. updateGeometry();
  85. update();
  86. }
  87. }
  88. QAntAbstractButton::ButtonState QAntAbstractButton::currentState() const {
  89. return m_state;
  90. }
  91. void QAntAbstractButton::paintText(QPainter &painter, const QRect &textRect) {
  92. painter.save();
  93. painter.setPen(palette().color(foregroundRole()));
  94. painter.setFont(font());
  95. painter.drawText(textRect, Qt::AlignCenter, m_text);
  96. painter.restore();
  97. }
  98. void QAntAbstractButton::paintIcon(QPainter &painter, const QRect &iconRect) {
  99. QIcon::Mode mode = QIcon::Normal;
  100. if (!isEnabled()) {
  101. mode = QIcon::Disabled;
  102. }
  103. else if (m_state == PressedState) {
  104. mode = QIcon::Selected;
  105. }
  106. m_icon.paint(&painter, iconRect, Qt::AlignCenter, mode);
  107. }
  108. void QAntAbstractButton::paintFocusIndicator(QPainter &painter) {
  109. painter.save();
  110. QPen pen(palette().highlight(), 1, Qt::DotLine);
  111. painter.setPen(pen);
  112. painter.setBrush(Qt::NoBrush);
  113. painter.drawRect(rect().adjusted(1, 1, -1, -1));
  114. painter.restore();
  115. }
  116. void QAntAbstractButton::paintBackground(QPainter &painter) {
  117. painter.fillRect(rect(), Qt::transparent);
  118. }
  119. void QAntAbstractButton::paintBorder(QPainter &painter) {
  120. // 移除边框绘制
  121. painter.save();
  122. QPen pen(palette().shadow(), 1);
  123. painter.setPen(pen);
  124. painter.setBrush(Qt::NoBrush);
  125. painter.drawRect(rect().adjusted(0, 0, -1, -1));
  126. painter.restore();
  127. }
  128. QRect QAntAbstractButton::calculateTextRect(const QRect &contentsRect) const {
  129. QFontMetrics fm(font());
  130. QRect textRect = fm.boundingRect(contentsRect, Qt::AlignCenter, m_text);
  131. if (!m_icon.isNull()) {
  132. textRect.moveLeft(contentsRect.left() + m_iconSize.width() + 4);
  133. }
  134. return textRect;
  135. }
  136. QRect QAntAbstractButton::calculateIconRect(const QRect &contentsRect) const {
  137. return QRect(contentsRect.left(), contentsRect.center().y() - m_iconSize.height() / 2,
  138. m_iconSize.width(), m_iconSize.height());
  139. }
  140. void QAntAbstractButton::paintEvent(QPaintEvent *event) {
  141. Q_UNUSED(event);
  142. QPainter painter(this);
  143. painter.setRenderHint(QPainter::Antialiasing);
  144. paintBackground(painter);
  145. switch (m_state) {
  146. case NormalState:
  147. paintNormalState(painter);
  148. break;
  149. case HoverState:
  150. paintHoverState(painter);
  151. break;
  152. case PressedState:
  153. paintPressedState(painter);
  154. break;
  155. case DisabledState:
  156. paintDisabledState(painter);
  157. break;
  158. case LoadingState:
  159. paintLoadingState(painter);
  160. break;
  161. }
  162. // paintBorder(painter);
  163. QRect contentsRect = rect().marginsRemoved(m_padding);
  164. if (!m_icon.isNull() && m_state != LoadingState) {
  165. QRect iconRect = calculateIconRect(contentsRect);
  166. paintIcon(painter, iconRect);
  167. }
  168. if (!m_text.isEmpty() && m_state != LoadingState) {
  169. QRect textRect = calculateTextRect(contentsRect);
  170. paintText(painter, textRect);
  171. }
  172. if (hasFocus()) {
  173. paintFocusIndicator(painter);
  174. }
  175. }
  176. void QAntAbstractButton::mousePressEvent(QMouseEvent *event) {
  177. if (event->button() == Qt::LeftButton && !m_loading && isEnabled()) {
  178. m_mousePressed = true;
  179. updateButtonState(PressedState);
  180. emit pressed();
  181. event->accept();
  182. }
  183. }
  184. void QAntAbstractButton::mouseReleaseEvent(QMouseEvent *event) {
  185. if (m_mousePressed && event->button() == Qt::LeftButton) {
  186. m_mousePressed = false;
  187. if (rect().contains(event->pos())) {
  188. startRippleEffect();
  189. emit clicked();
  190. updateButtonState(HoverState);
  191. } else {
  192. updateButtonState(NormalState);
  193. }
  194. }
  195. emit release();
  196. event->accept();
  197. }
  198. void QAntAbstractButton::mouseMoveEvent(QMouseEvent *event) {
  199. if (m_mousePressed) {
  200. if (rect().contains(event->pos())) {
  201. updateButtonState(PressedState);
  202. }
  203. else {
  204. QWidget::mouseMoveEvent(event);
  205. }
  206. }
  207. }
  208. void QAntAbstractButton::enterEvent(QEnterEvent *event) {
  209. if (isEnabled() && !m_loading && !m_mousePressed) {
  210. updateButtonState(HoverState);
  211. }
  212. QWidget::enterEvent(event);
  213. }
  214. void QAntAbstractButton::leaveEvent(QEvent *event) {
  215. if (isEnabled() && !m_loading) {
  216. updateButtonState(NormalState);
  217. }
  218. QWidget::leaveEvent(event);
  219. }
  220. void QAntAbstractButton::focusInEvent(QFocusEvent *event) {
  221. update();
  222. QWidget::focusInEvent(event);
  223. }
  224. void QAntAbstractButton::focusOutEvent(QFocusEvent *event) {
  225. update();
  226. QWidget::focusOutEvent(event);
  227. }
  228. void QAntAbstractButton::changeEvent(QEvent *event) {
  229. if (event->type() == QEvent::EnabledChange) {
  230. if (isEnabled()) {
  231. updateButtonState(NormalState);
  232. }
  233. else {
  234. updateButtonState(DisabledState);
  235. }
  236. emit enabledChanged(isEnabled());
  237. }
  238. QWidget::changeEvent(event);
  239. }
  240. void QAntAbstractButton::updateButtonState(ButtonState newState) {
  241. if (newState == m_state)
  242. return;
  243. ButtonState oldState = m_state;
  244. m_state = newState;
  245. update();
  246. }
  247. void QAntAbstractButton::startRippleEffect() {
  248. // 设置初始状态
  249. QColor effectColor = rippleColor();
  250. effectColor.setAlpha(120);
  251. m_shadowEffect->setColor(effectColor);
  252. m_shadowEffect->setBlurRadius(0);
  253. // 更新颜色动画
  254. QPropertyAnimation* colorAnim = qobject_cast<QPropertyAnimation*>(m_animationGroup->animationAt(1));
  255. if (colorAnim) {
  256. effectColor.setAlpha(0);
  257. colorAnim->setStartValue(m_shadowEffect->color());
  258. colorAnim->setEndValue(effectColor);
  259. }
  260. // 开始动画组
  261. m_animationGroup->start();
  262. }