139 lines
4.2 KiB
C++
139 lines
4.2 KiB
C++
|
#include "rangeslider.h"
|
||
|
#include <QPainter>
|
||
|
#include <QMouseEvent>
|
||
|
#include <QDebug>
|
||
|
|
||
|
RangeSlider::RangeSlider(int style,QWidget *parent)
|
||
|
: QWidget(parent) {
|
||
|
setMinimumSize(20, 240);
|
||
|
}
|
||
|
|
||
|
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 red handles (circles)
|
||
|
p.setPen(Qt::NoPen);
|
||
|
p.setBrush(Qt::red);
|
||
|
p.drawEllipse(QPointF(x, yLower), handleRadius, handleRadius);
|
||
|
p.drawEllipse(QPointF(x, yUpper), handleRadius, handleRadius);
|
||
|
|
||
|
// 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
|
||
|
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
|
||
|
}
|
||
|
|
||
|
void RangeSlider::drawTicks(QPainter *p) {
|
||
|
int tickCount = 11;
|
||
|
p->setPen(Qt::black);
|
||
|
p->setFont(QFont("Arial", 8));
|
||
|
int x = width() / 2 + handleRadius + 4;
|
||
|
|
||
|
for (int i = 0; i < tickCount; ++i) {
|
||
|
int val = m_min + i * (m_max - m_min) / (tickCount - 1);
|
||
|
int y = valueToY(val);
|
||
|
p->drawLine(x, y, x + 3, y); // 刻度宽度
|
||
|
p->drawText(x + 8, y + 4, QString::number(val));
|
||
|
}
|
||
|
}
|