#include "rangeslider.h" #include #include #include #include RangeSlider::RangeSlider(int style_,QWidget *parent) : QWidget(parent) { setMinimumSize(20, 240); style = style_; } void RangeSlider::setRange(int min, int max) { m_min = min; m_max = max; m_lower = qBound(m_min, m_lower, m_max); m_upper = qBound(m_lower, m_upper, m_max); update(); } void RangeSlider::setSliderWidth(int width) { sliderWidth = width; update(); // 更新界面 } float RangeSlider::lowerValue() const { return m_lower; } float RangeSlider::upperValue() const { return m_upper; } float RangeSlider::valueToY(float value) const { double ratio = (value - m_min) / double(m_max - m_min); return height() - handleRadius - ratio * (height() - 2 * handleRadius); } float RangeSlider::yToValue(float y) const { double ratio = (height() - handleRadius - y) / double(height() - 2 * handleRadius); ratio = qBound(0.0, ratio, 1.0); float rawValue = m_min + ratio * (m_max - m_min); float steppedValue = qRound(rawValue * 10) / 10.0f; return qBound(m_min, steppedValue, m_max); } RangeSlider::HandleType RangeSlider::handleHitTest(float y) const { int yLower = valueToY(m_lower); int yUpper = valueToY(m_upper); if (qAbs(y - yLower) <= handleRadius + 2) return LowerHandle; if (qAbs(y - yUpper) <= handleRadius + 2) return UpperHandle; return NoHandle; } void RangeSlider::mousePressEvent(QMouseEvent *event) { currentHandle = handleHitTest(event->pos().y()); } void RangeSlider::mouseMoveEvent(QMouseEvent *event) { if (currentHandle == NoHandle) return; float val = yToValue(event->pos().y()); if (currentHandle == LowerHandle) { m_lower = qBound(m_min, val, m_upper); } else if (currentHandle == UpperHandle) { m_upper = qBound(m_lower, val, m_max); } update(); emit rangeChanged(m_lower, m_upper); } void RangeSlider::mouseReleaseEvent(QMouseEvent *) { currentHandle = NoHandle; } void RangeSlider::paintEvent(QPaintEvent *) { QPainter p(this); p.setRenderHint(QPainter::Antialiasing); int x = width() / 2; int yLower = valueToY(m_lower); int yUpper = valueToY(m_upper); // Draw Temperature-style background (gradient) drawTemperatureStyle(&p); // Draw selected range (green) // Draw selected range (green) p.setPen(Qt::NoPen); p.setBrush(Qt::green); p.drawRect(x - sliderWidth / 2, yUpper, sliderWidth, yLower - yUpper); // Draw simple black handles (lines) p.setPen(QPen(Qt::black, 2)); p.drawLine(x - sliderWidth / 2, yLower, x + sliderWidth, yLower); p.drawLine(x - sliderWidth / 2, yUpper, x + sliderWidth, yUpper); // Draw ticks drawTicks(&p); } void RangeSlider::setLowerValue(float val) { m_lower = qBound(m_min, val, m_upper); update(); emit rangeChanged(m_lower, m_upper); } void RangeSlider::setUpperValue(float val) { m_upper = qBound(m_lower, val, m_max); update(); emit rangeChanged(m_lower, m_upper); } void RangeSlider::drawTemperatureStyle(QPainter *p) { int x = width() / 2; int yTop = handleRadius; int yBottom = height() - handleRadius; // Draw border (black) p->setPen(Qt::black); p->setBrush(Qt::NoBrush); p->drawRect(x - sliderWidth / 2, yTop, sliderWidth, yBottom - yTop); // Draw yellow outside the range if(style != 0){ p->setBrush(Qt::red); p->drawRect(x - sliderWidth / 2, yTop, sliderWidth, valueToY(m_lower) - yTop); // Above lower range p->drawRect(x - sliderWidth / 2, valueToY(m_upper), sliderWidth, yBottom - valueToY(m_upper)); // Below upper range }else{ p->setBrush(Qt::yellow); p->drawRect(x - sliderWidth / 2, yTop, sliderWidth, valueToY(m_lower) - yTop); // Above lower range p->drawRect(x - sliderWidth / 2, valueToY(m_upper), sliderWidth, yBottom - valueToY(m_upper)); // Below upper range } // Draw green inside the range p->setBrush(Qt::green); p->drawRect(x - sliderWidth / 2, valueToY(m_upper), sliderWidth, valueToY(m_lower) - valueToY(m_upper)); // Green area } int RangeSlider::niceStep(int range, int maxLabels) { double rawStep = static_cast(range) / maxLabels; // 取一个"好看"的步长 double magnitude = pow(10, floor(log10(rawStep))); // 10 的整数次幂 double residual = rawStep / magnitude; double niceResidual; if (residual < 1.5) niceResidual = 1; else if (residual < 3) niceResidual = 2; else if (residual < 7) niceResidual = 5; else niceResidual = 10; return static_cast(niceResidual * magnitude); } void RangeSlider::drawTicks(QPainter *p) { int range = m_max - m_min; int labelStep = niceStep(range, 10); int minorStep = qMax(1, labelStep / 5); int x = width() / 2 + handleRadius + 4; p->setFont(QFont("Arial", 8)); for (int val = m_min; val <= m_max; val += minorStep) { int y = valueToY(val); if (val % labelStep == 0) { p->setPen(QPen(Qt::black, 1.5)); // 主刻度 p->drawLine(x, y, x + 6, y); p->drawText(x + 10, y + 4, QString::number(val)); } else { p->setPen(QPen(Qt::gray, 1)); // 次刻度 p->drawLine(x, y, x + 3, y); } } }