主要是运用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);