TSI_Config/rangeslider.cpp

172 lines
5.3 KiB
C++
Raw Permalink Normal View History

2025-04-17 14:06:21 +08:00
#include "rangeslider.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
2025-04-19 16:25:33 +08:00
#include <cmath>
2025-04-17 14:06:21 +08:00
2025-04-19 16:25:33 +08:00
RangeSlider::RangeSlider(int style_,QWidget *parent)
2025-04-17 14:06:21 +08:00
: QWidget(parent) {
setMinimumSize(20, 240);
2025-04-19 16:25:33 +08:00
style = style_;
2025-04-17 14:06:21 +08:00
}
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);
2025-04-19 16:25:33 +08:00
// 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);
2025-04-17 14:06:21 +08:00
// 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
2025-04-19 16:25:33 +08:00
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
}
2025-04-17 14:06:21 +08:00
// 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
}
2025-04-19 16:25:33 +08:00
int RangeSlider::niceStep(int range, int maxLabels) {
double rawStep = static_cast<double>(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<int>(niceResidual * magnitude);
}
2025-04-17 14:06:21 +08:00
void RangeSlider::drawTicks(QPainter *p) {
2025-04-19 16:25:33 +08:00
int range = m_max - m_min;
int labelStep = niceStep(range, 10);
int minorStep = qMax(1, labelStep / 5);
2025-04-17 14:06:21 +08:00
int x = width() / 2 + handleRadius + 4;
2025-04-19 16:25:33 +08:00
p->setFont(QFont("Arial", 8));
2025-04-17 14:06:21 +08:00
2025-04-19 16:25:33 +08:00
for (int val = m_min; val <= m_max; val += minorStep) {
2025-04-17 14:06:21 +08:00
int y = valueToY(val);
2025-04-19 16:25:33 +08:00
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);
}
2025-04-17 14:06:21 +08:00
}
}