feat/dataset-detail-chart #5
|
|
@ -19,68 +19,47 @@ void ColorBarWidget::setColorScale(const core::ColorScale& scale) {
|
|||
}
|
||||
|
||||
void ColorBarWidget::paintEvent(QPaintEvent* /*event*/) {
|
||||
auto stops = scale_.stops();
|
||||
if (stops.empty()) return;
|
||||
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
const int W = width();
|
||||
const int H = height();
|
||||
p.fillRect(0, 0, W, H, Qt::white); // 白底,对齐原版
|
||||
|
||||
auto stops = scale_.stops();
|
||||
if (stops.size() < 2) return;
|
||||
|
||||
// 横向色带区域(顶部)
|
||||
const int barY = 2;
|
||||
const int barH = kBarHeight;
|
||||
// 等宽色带:每相邻断点一格,等宽(对齐原版图例,非按值比例)。
|
||||
const int nSeg = static_cast<int>(stops.size()) - 1;
|
||||
auto segX = [&](int i) { return static_cast<int>(static_cast<double>(i) / nSeg * (W - 1)); };
|
||||
|
||||
// 边界值
|
||||
double minVal = stops.front().first;
|
||||
double maxVal = stops.back().first;
|
||||
double range = maxVal - minVal;
|
||||
if (range <= 0.0) range = 1.0;
|
||||
|
||||
// 绘制每段色格(相邻断点间一格)
|
||||
for (std::size_t i = 0; i + 1 < stops.size(); ++i) {
|
||||
double posL = (stops[i].first - minVal) / range;
|
||||
double posR = (stops[i + 1].first - minVal) / range;
|
||||
int xL = static_cast<int>(posL * (W - 1));
|
||||
int xR = static_cast<int>(posR * (W - 1));
|
||||
for (int i = 0; i < nSeg; ++i) {
|
||||
int xL = segX(i), xR = segX(i + 1);
|
||||
if (xR <= xL) xR = xL + 1;
|
||||
const auto& c = stops[i].second;
|
||||
p.fillRect(xL, barY, xR - xL, barH, QColor(c.r, c.g, c.b, c.a));
|
||||
}
|
||||
// 最后一段(末断点颜色填到边缘)
|
||||
{
|
||||
double posL = (stops.back().first - minVal) / range;
|
||||
int xL = static_cast<int>(posL * (W - 1));
|
||||
const auto& c = stops.back().second;
|
||||
p.fillRect(xL, barY, W - xL, barH, QColor(c.r, c.g, c.b, c.a));
|
||||
}
|
||||
|
||||
// 外边框
|
||||
p.setPen(QPen(QColor(80, 80, 80), 1));
|
||||
p.setPen(QPen(QColor(120, 120, 120), 1));
|
||||
p.drawRect(0, barY, W - 1, barH - 1);
|
||||
|
||||
// 刻度区(色带下方)
|
||||
// 边界值标签(深色文字,白底可见),在各分格边界下方。
|
||||
QFont font = p.font();
|
||||
font.setPixelSize(kFontSize);
|
||||
p.setFont(font);
|
||||
p.setPen(QColor(200, 200, 200));
|
||||
|
||||
const int tickY = barY + barH + 1;
|
||||
|
||||
for (const auto& [val, color] : stops) {
|
||||
double pos = (val - minVal) / range;
|
||||
int x = static_cast<int>(pos * (W - 1));
|
||||
// 刻度短线
|
||||
p.drawLine(x, tickY, x, tickY + kTickHeight);
|
||||
// 数值文字(右对齐到刻度位置,避免越界)
|
||||
QString label = QString::number(val, 'g', 4);
|
||||
p.setPen(QColor(60, 60, 60));
|
||||
QFontMetrics fm(font);
|
||||
const int tickY = barY + barH + 1;
|
||||
for (int i = 0; i <= nSeg; ++i) {
|
||||
int x = segX(i);
|
||||
p.drawLine(x, tickY, x, tickY + kTickHeight);
|
||||
const QString label = QString::number(stops[i].first, 'g', 4);
|
||||
int tw = fm.horizontalAdvance(label);
|
||||
int tx = x - tw / 2;
|
||||
if (tx < 0) tx = 0;
|
||||
if (tx + tw > W) tx = W - tw;
|
||||
p.drawText(tx, H - 1, label);
|
||||
p.drawText(tx, H - 2, label);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <qwt_plot_canvas.h>
|
||||
#include <qwt_plot_panner.h>
|
||||
#include <qwt_plot_magnifier.h>
|
||||
#include <qwt_plot_marker.h>
|
||||
|
||||
namespace geopro::app {
|
||||
|
||||
|
|
@ -58,8 +59,29 @@ RawDataChartView::RawDataChartView(QWidget* parent) : QWidget(parent) {
|
|||
plot_->enableAxis(QwtPlot::xBottom, false);
|
||||
plot_->enableAxis(QwtPlot::yLeft, true);
|
||||
|
||||
// 深色背景风格
|
||||
plot_->setCanvasBackground(QBrush(QColor(30, 30, 30)));
|
||||
// 白底浅色(对齐原版 web 图表,与 App 暗色主题独立):画布白、轴文字深灰。
|
||||
plot_->setCanvasBackground(QBrush(Qt::white));
|
||||
plot_->setAutoFillBackground(true);
|
||||
{
|
||||
QPalette pal = plot_->palette();
|
||||
pal.setColor(QPalette::Window, Qt::white);
|
||||
pal.setColor(QPalette::WindowText, QColor(90, 90, 90));
|
||||
pal.setColor(QPalette::Text, QColor(90, 90, 90));
|
||||
plot_->setPalette(pal);
|
||||
}
|
||||
|
||||
// 过原点零线(对齐原版 zeroline:x=0 竖线 + y=0 横线 → "四象限"观感)。
|
||||
auto* zeroX = new QwtPlotMarker();
|
||||
zeroX->setLineStyle(QwtPlotMarker::VLine);
|
||||
zeroX->setXValue(0.0);
|
||||
zeroX->setLinePen(QColor(180, 180, 180), 1.0);
|
||||
zeroX->setXAxis(QwtPlot::xTop);
|
||||
zeroX->attach(plot_);
|
||||
auto* zeroY = new QwtPlotMarker();
|
||||
zeroY->setLineStyle(QwtPlotMarker::HLine);
|
||||
zeroY->setYValue(0.0);
|
||||
zeroY->setLinePen(QColor(180, 180, 180), 1.0);
|
||||
zeroY->attach(plot_);
|
||||
|
||||
// 交互:Panner(左键拖动平移)+ Magnifier(滚轮缩放)
|
||||
auto* panner = new QwtPlotPanner(plot_->canvas());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "panels/chart/ScatterPlotItem.hpp"
|
||||
#include <QPainter>
|
||||
#include <qwt_plot.h>
|
||||
#include <qwt_scale_map.h>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
|
@ -10,6 +11,10 @@ ScatterPlotItem::ScatterPlotItem()
|
|||
: QwtPlotItem() {
|
||||
setTitle("Scatter");
|
||||
setRenderHint(QwtPlotItem::RenderAntialiased, false);
|
||||
// 关联到 x 顶轴(原数据 x 轴在顶部;与 RawDataChartView 的 setAxisScale(xTop,...) 一致,
|
||||
// 否则项默认用 xBottom 的(未设置/自动)刻度 → 散点被错误压缩)。
|
||||
setXAxis(QwtPlot::xTop);
|
||||
setYAxis(QwtPlot::yLeft);
|
||||
}
|
||||
|
||||
void ScatterPlotItem::setData(const core::ScatterField& field, ColorMapService* svc) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue