QSlider 实现多段不同颜色

主要是运用QProxyStyle进行自定义绘制,下面是实现的效果
在这里插入图片描述

class msliderstyle : public QProxyStyle {
    Q_OBJECT
public:

    explicit msliderstyle(QStyle* style = nullptr) : QProxyStyle(style) {}
    // 设置分段信息
    void setSegments(const QVector<QPair<qreal, int>>& segments) {
        m_segments = segments;
    }
    // 重写绘制方法
    void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option,
                            QPainter* painter, const QWidget* widget) const override {
        if (control == CC_Slider) {
            if (const QStyleOptionSlider* sliderOption = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
                drawSegments(painter, sliderOption, widget);
                drawHandle(painter, sliderOption, widget);
                return;
            }
        }
        QProxyStyle::drawComplexControl(control, option, painter, widget);
    }

private:
    void drawSegments(QPainter* painter, const QStyleOptionSlider* option, const QWidget* widget) const {
        QRect grooveRect = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
        // 调整轨道高度,保持居中
        grooveRect.setHeight(4); // 固定高度4像素
        grooveRect.moveCenter(subControlRect(CC_Slider, option, SC_SliderGroove, widget).center());
        qreal min = option->minimum;
        qreal max = option->maximum;
        qreal range = max - min;
        bool isHorizontal = option->orientation == Qt::Horizontal;
        for (int i = 0; i < m_segments.size(); ++i) {
            qreal startPos = m_segments[i].first;
            qreal endPos = (i == m_segments.size() - 1) ? max : m_segments[i+1].first;

            qreal startRatio = (startPos - min) / range;
            qreal endRatio = (endPos - min) / range;

            QRect segmentRect;
            if (isHorizontal) {
                int startX = grooveRect.left() + startRatio * grooveRect.width();
                int endX = grooveRect.left() + endRatio * grooveRect.width();
                segmentRect = QRect(startX, grooveRect.top(), endX - startX, grooveRect.height());
            } else {
                int startY = grooveRect.bottom() - startRatio * grooveRect.height();
                int endY = grooveRect.bottom() - endRatio * grooveRect.height();
                segmentRect = QRect(grooveRect.left(), endY, grooveRect.width(), startY - endY);
            }
            switch (m_segments[i].second) {
            case 0:
                painter->fillRect(segmentRect, QColor("#5B7DFF"));
                break;
            case 1:
                painter->fillRect(segmentRect, QColor("#BD68D9"));
                break;
            default:
                painter->fillRect(segmentRect, QColor("#5B7DFF"));
                break;
            }

        }

        // // 绘制圆角边框
        // painter->setPen(QPen(Qt::gray, 1));
        // painter->setBrush(Qt::NoBrush);
        // painter->setRenderHint(QPainter::Antialiasing);
        // painter->drawRoundedRect(grooveRect, 4, 4);
    }

    void drawHandle(QPainter* painter, const QStyleOptionSlider* option, const QWidget* widget) const {
        QRect handleRect = subControlRect(CC_Slider, option, SC_SliderHandle, widget);

        // 调整滑块为小圆点
        int diameter = 12; // 直径12像素
        handleRect.setSize(QSize(diameter, diameter));
        handleRect.moveCenter(QPoint(
            handleRect.center().x(),
            subControlRect(CC_Slider, option, SC_SliderGroove, widget).center().y()
            ));

        // 绘制纯白圆点
        painter->setRenderHint(QPainter::Antialiasing);
        painter->setPen(Qt::NoPen);
        painter->setBrush(Qt::white);
        painter->drawEllipse(handleRect);

        // 可选: 添加轻微阴影效果
        painter->setPen(QPen(QColor(0, 0, 0, 30), 1));
        painter->setBrush(Qt::NoBrush);
        painter->drawEllipse(handleRect.adjusted(1, 1, -1, -1));
    }

    QVector<QPair<qreal, int>> m_segments;
};

下面是具体的应用

   msliderstyle *mSltyle = new msliderstyle();
    // 设置范围
    ui->horizontalSlider->setRange(0, 100);

    // 设置分段
    QVector<QPair<qreal, int>> segments = {
        {0, 0},         // 0-20
        {20, 1},     // 20-70
        {70, 0}      // 70-100
    };
    mSltyle->setSegments(segments);
    ui->horizontalSlider->setStyle(mSltyle);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小加藤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值