#include "ElaScrollBarStyle.h" #include #include #include #include #include #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(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); } }