Files
cbh/ElaWidgetTools/DeveloperComponents/ElaScrollBarStyle.cpp
2025-09-20 01:41:33 +08:00

163 lines
8.3 KiB
C++

#include "ElaScrollBarStyle.h"
#include <QPainter>
#include <QPainterPath>
#include <QPropertyAnimation>
#include <QStyleOptionSlider>
#include <QtMath>
#include "ElaScrollBar.h"
#include "ElaTheme.h"
ElaScrollBarStyle::ElaScrollBarStyle(QStyle *style) {
_pIsExpand = false;
_pOpacity = 0;
_pScrollBar = nullptr;
_pSliderExtent = 2.4;
_themeMode = eTheme->getThemeMode();
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
}
ElaScrollBarStyle::~ElaScrollBarStyle() {}
void ElaScrollBarStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter,
const QWidget *widget) const {
// QStyle::SC_ScrollBarGroove QStyle::SC_ScrollBarAddLine QStyle::SC_ScrollBarSubLine上指示器
switch (control) {
case QStyle::CC_ScrollBar: {
if (const QStyleOptionSlider *sopt = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::NoPen);
QRect scrollBarRect = sopt->rect;
if (_pIsExpand) {
// 背景绘制
painter->setOpacity(_pOpacity);
painter->setPen(Qt::NoPen);
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
painter->drawRoundedRect(scrollBarRect, 6, 6);
// 指示器绘制 center()在此处不适用 存在外围边距宽度 需手动计算
int sideLength = 8;
painter->setBrush(ElaThemeColor(_themeMode, ScrollBarHandle));
if (sopt->orientation == Qt::Horizontal) {
QRect leftIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSubLine, widget);
QRect rightIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarAddLine, widget);
// 左三角
qreal centerLeftX = leftIndicatorRect.x() + leftIndicatorRect.width() / 2;
qreal centerRightX = rightIndicatorRect.x() + rightIndicatorRect.width() / 2;
qreal centerY = leftIndicatorRect.height() / 2;
QPainterPath leftPath;
leftPath.moveTo(centerLeftX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY);
leftPath.lineTo(centerLeftX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY + sideLength / 2);
leftPath.lineTo(centerLeftX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY - sideLength / 2);
leftPath.closeSubpath();
painter->drawPath(leftPath);
// 右三角
QPainterPath rightPath;
rightPath.moveTo(centerRightX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY);
rightPath.lineTo(centerRightX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY + sideLength / 2);
rightPath.lineTo(centerRightX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY - sideLength / 2);
rightPath.closeSubpath();
painter->drawPath(rightPath);
} else {
QRect upIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSubLine, widget);
QRect downIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarAddLine, widget);
qreal centerToTop = (sideLength / 2) / qCos(30 * M_PI / 180.0);
qreal centerToBottom = (sideLength / 2) * qTan(30 * M_PI / 180.0);
// 上三角
qreal centerX = upIndicatorRect.width() / 2.0;
qreal centerUpY = upIndicatorRect.center().y() + 2;
qreal centerDownY = downIndicatorRect.center().y() + 2;
QPainterPath upPath;
upPath.moveTo(centerX, centerUpY - centerToTop);
upPath.lineTo(centerX + sideLength / 2, centerUpY + centerToBottom);
upPath.lineTo(centerX - sideLength / 2, centerUpY + centerToBottom);
upPath.closeSubpath();
painter->drawPath(upPath);
// 下三角
QPainterPath downPath;
downPath.moveTo(centerX, centerDownY + centerToBottom);
downPath.lineTo(centerX + sideLength / 2, centerDownY - centerToTop);
downPath.lineTo(centerX - sideLength / 2, centerDownY - centerToTop);
downPath.closeSubpath();
painter->drawPath(downPath);
}
}
painter->setOpacity(1);
// 滑块绘制
QRectF sliderRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSlider, widget);
painter->setBrush(ElaThemeColor(_themeMode, ScrollBarHandle));
if (sopt->orientation == Qt::Horizontal) {
sliderRect.setRect(sliderRect.x(), sliderRect.bottom() - _sliderMargin - _pSliderExtent, sliderRect.width(), _pSliderExtent);
} else {
sliderRect.setRect(sliderRect.right() - _sliderMargin - _pSliderExtent, sliderRect.y(), _pSliderExtent, sliderRect.height());
}
painter->drawRoundedRect(sliderRect, _pSliderExtent / 2.0, _pSliderExtent / 2.0);
painter->restore();
}
return;
}
default: {
break;
}
}
QProxyStyle::drawComplexControl(control, option, painter, widget);
}
int ElaScrollBarStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const {
// qDebug() << metric << QProxyStyle::pixelMetric(metric, option, widget);
switch (metric) {
case QStyle::PM_ScrollBarExtent: {
return _scrollBarExtent;
}
default: {
break;
}
}
return QProxyStyle::pixelMetric(metric, option, widget);
}
int ElaScrollBarStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const {
if (hint == QStyle::SH_ScrollBar_LeftClickAbsolutePosition) {
return true;
}
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
void ElaScrollBarStyle::startExpandAnimation(bool isExpand) {
if (isExpand) {
_pIsExpand = true;
QPropertyAnimation *opacityAnimation = new QPropertyAnimation(this, "pOpacity");
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=]() { _pScrollBar->update(); });
opacityAnimation->setDuration(250);
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
opacityAnimation->setStartValue(_pOpacity);
opacityAnimation->setEndValue(1);
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
QPropertyAnimation *extentAnimation = new QPropertyAnimation(this, "pSliderExtent");
extentAnimation->setDuration(250);
extentAnimation->setEasingCurve(QEasingCurve::InOutSine);
extentAnimation->setStartValue(_pSliderExtent);
extentAnimation->setEndValue(_scrollBarExtent - 2 * _sliderMargin);
extentAnimation->start(QAbstractAnimation::DeleteWhenStopped);
} else {
QPropertyAnimation *opacityAnimation = new QPropertyAnimation(this, "pOpacity");
connect(opacityAnimation, &QPropertyAnimation::finished, this, [=]() { _pIsExpand = false; });
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=]() { _pScrollBar->update(); });
opacityAnimation->setDuration(250);
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
opacityAnimation->setStartValue(_pOpacity);
opacityAnimation->setEndValue(0);
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
QPropertyAnimation *extentAnimation = new QPropertyAnimation(this, "pSliderExtent");
extentAnimation->setDuration(250);
extentAnimation->setEasingCurve(QEasingCurve::InOutSine);
extentAnimation->setStartValue(_pSliderExtent);
extentAnimation->setEndValue(2.4);
extentAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
}