2026-03-09 16:50:21 +08:00
|
|
|
|
#include "CustomQwtPlot.h"
|
|
|
|
|
|
#include <QwtPlotCurve>
|
|
|
|
|
|
#include <QwtLegend>
|
|
|
|
|
|
#include <QwtPlotCanvas>
|
2026-03-12 20:23:55 +08:00
|
|
|
|
#include <QwtText>
|
|
|
|
|
|
#include <QwtPlotMarker>
|
2026-03-13 15:36:08 +08:00
|
|
|
|
#include <QwtPlotZoneItem>
|
|
|
|
|
|
#include <QwtScaleMap>
|
|
|
|
|
|
#include <QwtScaleDiv>
|
2026-03-09 16:50:21 +08:00
|
|
|
|
#include <QPen>
|
2026-03-13 15:36:08 +08:00
|
|
|
|
#include <QMouseEvent>
|
|
|
|
|
|
#include <QwtScaleWidget>
|
2026-03-17 10:50:33 +08:00
|
|
|
|
#include <QwtPlotPicker>
|
|
|
|
|
|
#include <QwtPlotShapeItem>
|
|
|
|
|
|
#include <QwtPickerDragRectMachine>
|
2026-03-30 11:55:15 +08:00
|
|
|
|
#include <QwtPlotMagnifier>
|
2026-03-17 10:50:33 +08:00
|
|
|
|
#include <QDebug>
|
2026-03-09 16:50:21 +08:00
|
|
|
|
|
2026-03-30 11:55:15 +08:00
|
|
|
|
CustomQwtPlotAxisPanner::CustomQwtPlotAxisPanner(QwtScaleWidget *scale_widget)
|
|
|
|
|
|
: QwtPlotPanner(scale_widget)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (scale_widget) {
|
|
|
|
|
|
if (scale_widget->alignment() == QwtScaleDraw::BottomScale) {
|
|
|
|
|
|
this->setOrientations(Qt::Horizontal);
|
|
|
|
|
|
} else if (scale_widget->alignment() == QwtScaleDraw::LeftScale) {
|
|
|
|
|
|
this->setOrientations(Qt::Vertical);
|
|
|
|
|
|
} else if (scale_widget->alignment() == QwtScaleDraw::TopScale) {
|
|
|
|
|
|
this->setOrientations(Qt::Horizontal);
|
|
|
|
|
|
} else if (scale_widget->alignment() == QwtScaleDraw::RightScale) {
|
|
|
|
|
|
this->setOrientations(Qt::Vertical);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CustomQwtPlotAxisPanner::~CustomQwtPlotAxisPanner()
|
|
|
|
|
|
{
|
|
|
|
|
|
qDebug() << "~CustomQwtPlotXaxisPanner";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlotAxisPanner::moveCanvas(int dx, int dy)
|
|
|
|
|
|
{
|
|
|
|
|
|
QwtScaleWidget* scale_widget = dynamic_cast<QwtScaleWidget*>(this->canvas());
|
|
|
|
|
|
if (scale_widget) {
|
|
|
|
|
|
if (scale_widget->alignment() == QwtScaleDraw::BottomScale) {
|
|
|
|
|
|
QwtPlotPanner::moveCanvas(dx, 0);
|
|
|
|
|
|
} else if (scale_widget->alignment() == QwtScaleDraw::LeftScale) {
|
|
|
|
|
|
QwtPlotPanner::moveCanvas(0, dy);
|
|
|
|
|
|
} else if (scale_widget->alignment() == QwtScaleDraw::TopScale) {
|
|
|
|
|
|
QwtPlotPanner::moveCanvas(dx, 0);
|
|
|
|
|
|
} else if (scale_widget->alignment() == QwtScaleDraw::RightScale) {
|
|
|
|
|
|
QwtPlotPanner::moveCanvas(0, dy);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CustomQwtPlotXaxisMagnifier::CustomQwtPlotXaxisMagnifier(QWidget *canvas)
|
|
|
|
|
|
// : QwtPlotMagnifier(canvas)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// CustomQwtPlotXaxisMagnifier::~CustomQwtPlotXaxisMagnifier()
|
|
|
|
|
|
// {
|
|
|
|
|
|
// qDebug() << "~CustomQwtPlotXaxisMagnifier";
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// void CustomQwtPlotXaxisMagnifier::rescale(double factor)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// factor = qBound(0.1, factor, 10.0);
|
|
|
|
|
|
|
|
|
|
|
|
// QwtScaleMap x_map = plot()->canvasMap(QwtPlot::xBottom);
|
|
|
|
|
|
// double center = x_map.invTransform(plot()->canvas()->width() / 2);
|
|
|
|
|
|
// plot()->setAxisScale(
|
|
|
|
|
|
// QwtPlot::xBottom,
|
|
|
|
|
|
// center - (center - x_map.s1()) * factor,
|
|
|
|
|
|
// center + (x_map.s2() - center) * factor
|
|
|
|
|
|
// );
|
|
|
|
|
|
// plot()->replot();
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
CustomQwtPlotXaxisSelector::CustomQwtPlotXaxisSelector(QWidget *canvas)
|
|
|
|
|
|
: QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,
|
|
|
|
|
|
QwtPicker::NoRubberBand,
|
|
|
|
|
|
QwtPicker::AlwaysOn,
|
|
|
|
|
|
canvas)
|
|
|
|
|
|
, _min_x(0.0)
|
|
|
|
|
|
, _max_x(0.0)
|
|
|
|
|
|
{
|
|
|
|
|
|
this->setStateMachine(new QwtPickerDragRectMachine());
|
|
|
|
|
|
this->setRubberBandPen(QPen(Qt::NoPen));
|
|
|
|
|
|
|
|
|
|
|
|
_overlay = new QwtPlotShapeItem;
|
|
|
|
|
|
_overlay->setRenderHint(QwtPlotItem::RenderAntialiased);
|
|
|
|
|
|
_overlay->setPen(QPen(Qt::red, 2));
|
|
|
|
|
|
_overlay->setBrush(QBrush(QColor(0, 120, 210, 50)));
|
|
|
|
|
|
_overlay->setZ(100);
|
|
|
|
|
|
_overlay->attach(plot());
|
|
|
|
|
|
_overlay->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CustomQwtPlotXaxisSelector::~CustomQwtPlotXaxisSelector()
|
|
|
|
|
|
{
|
|
|
|
|
|
qDebug() << "~CustomQwtPlotXaxisSelector";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double CustomQwtPlotXaxisSelector::selectedMinX() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return _min_x;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double CustomQwtPlotXaxisSelector::selectedMaxX() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return _max_x;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlotXaxisSelector::clearSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
_min_x = 0.0;
|
|
|
|
|
|
_max_x = 0.0;
|
|
|
|
|
|
if (_overlay)
|
|
|
|
|
|
_overlay->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlotXaxisSelector::move(const QPoint & pos)
|
|
|
|
|
|
{
|
|
|
|
|
|
QPolygon points = pickedPoints();
|
|
|
|
|
|
if (points.size() < 2) {
|
|
|
|
|
|
clearSelection();
|
|
|
|
|
|
return QwtPlotPicker::move(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QPointF p1 = invTransform(points.first());
|
|
|
|
|
|
QPointF p2 = invTransform(points.last());
|
|
|
|
|
|
|
|
|
|
|
|
// 计算X范围
|
|
|
|
|
|
_min_x = qMin(p1.x(), p2.x());
|
|
|
|
|
|
_max_x = qMax(p1.x(), p2.x());
|
|
|
|
|
|
|
|
|
|
|
|
// Y轴铺满
|
|
|
|
|
|
double y_min = plot()->axisScaleDiv(QwtPlot::yLeft).lowerBound();
|
|
|
|
|
|
double y_max = plot()->axisScaleDiv(QwtPlot::yLeft).upperBound();
|
|
|
|
|
|
QRectF area(_min_x, y_min, _max_x - _min_x, y_max - y_min);
|
|
|
|
|
|
|
|
|
|
|
|
_overlay->setRect(area);
|
|
|
|
|
|
_overlay->setVisible(true);
|
|
|
|
|
|
plot()->replot();
|
|
|
|
|
|
|
|
|
|
|
|
QwtPlotPicker::move(pos);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CustomQwtPlotXaxisSelector::end(bool ok)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ok) {
|
|
|
|
|
|
clearSelection();
|
|
|
|
|
|
return QwtPlotPicker::end(ok);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_overlay->isVisible()) {
|
|
|
|
|
|
_overlay->setVisible(false);
|
|
|
|
|
|
plot()->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( (_max_x - _min_x) > 3 ) {
|
|
|
|
|
|
emit selectionFinished(_min_x, _max_x);
|
|
|
|
|
|
}
|
|
|
|
|
|
return QwtPlotPicker::end(ok);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 16:50:21 +08:00
|
|
|
|
CustomQwtPlot::CustomQwtPlot(QWidget *parent)
|
|
|
|
|
|
: QwtPlot(parent)
|
|
|
|
|
|
{
|
2026-03-30 11:55:15 +08:00
|
|
|
|
|
2026-03-13 15:36:08 +08:00
|
|
|
|
}
|
2026-03-09 16:50:21 +08:00
|
|
|
|
|
2026-03-17 10:50:33 +08:00
|
|
|
|
CustomQwtPlot::~CustomQwtPlot()
|
|
|
|
|
|
{
|
|
|
|
|
|
qDebug() << "~CustomQwtPlot";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-30 11:55:15 +08:00
|
|
|
|
void CustomQwtPlot::SetAxisDragScale(Axis axis_id, bool enable)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (axis_id) {
|
|
|
|
|
|
case xBottom: {
|
|
|
|
|
|
if ( enable ) {
|
|
|
|
|
|
if ( nullptr == _x_axis_panner ) {
|
|
|
|
|
|
_x_axis_panner = new CustomQwtPlotAxisPanner(this->axisWidget(QwtPlot::xBottom));
|
|
|
|
|
|
_x_axis_panner->setMouseButton(Qt::LeftButton);
|
|
|
|
|
|
_x_axis_panner->setAxisEnabled(QwtPlot::xBottom, true);
|
|
|
|
|
|
_x_axis_panner->setAxisEnabled(QwtPlot::yLeft, false);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
_x_axis_panner->setAxisEnabled(QwtPlot::xBottom, true);
|
|
|
|
|
|
_x_axis_panner->setAxisEnabled(QwtPlot::yLeft, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( nullptr == _x_axis_magnifier ) {
|
|
|
|
|
|
_x_axis_magnifier = new QwtPlotMagnifier(this->axisWidget(QwtPlot::xBottom));
|
|
|
|
|
|
_x_axis_magnifier->setAxisEnabled(QwtPlot::xBottom, true);
|
|
|
|
|
|
_x_axis_magnifier->setAxisEnabled(QwtPlot::yLeft, false);
|
|
|
|
|
|
_x_axis_magnifier->setWheelFactor(1.1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
_x_axis_magnifier->setAxisEnabled(QwtPlot::xBottom, true);
|
|
|
|
|
|
_x_axis_magnifier->setAxisEnabled(QwtPlot::yLeft, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (_x_axis_panner) {
|
|
|
|
|
|
delete _x_axis_panner;
|
|
|
|
|
|
_x_axis_panner = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_x_axis_magnifier) {
|
|
|
|
|
|
delete _x_axis_magnifier;
|
|
|
|
|
|
_x_axis_magnifier = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
case yLeft: {
|
|
|
|
|
|
if ( enable ) {
|
|
|
|
|
|
if (nullptr == _y_axis_panner) {
|
|
|
|
|
|
_y_axis_panner = new CustomQwtPlotAxisPanner(this->axisWidget(QwtPlot::yLeft));
|
|
|
|
|
|
_y_axis_panner->setMouseButton(Qt::LeftButton);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
_y_axis_panner->setAxisEnabled(QwtPlot::xBottom, false);
|
|
|
|
|
|
_y_axis_panner->setAxisEnabled(QwtPlot::yLeft, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nullptr == _y_axis_magnifier) {
|
|
|
|
|
|
_y_axis_magnifier = new QwtPlotMagnifier(this->axisWidget(QwtPlot::yLeft));
|
|
|
|
|
|
_y_axis_magnifier->setAxisEnabled(QwtPlot::xBottom, false);
|
|
|
|
|
|
_y_axis_magnifier->setAxisEnabled(QwtPlot::yLeft, true);
|
|
|
|
|
|
_y_axis_magnifier->setWheelFactor(1.1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
_y_axis_magnifier->setAxisEnabled(QwtPlot::xBottom, false);
|
|
|
|
|
|
_y_axis_magnifier->setAxisEnabled(QwtPlot::yLeft, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (_y_axis_panner) {
|
|
|
|
|
|
delete _y_axis_panner;
|
|
|
|
|
|
_y_axis_panner = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (_y_axis_magnifier) {
|
|
|
|
|
|
delete _y_axis_magnifier;
|
|
|
|
|
|
_y_axis_magnifier = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::SetAxisInitRange(Axis axis_id, double min, double max)
|
2026-03-13 15:36:08 +08:00
|
|
|
|
{
|
2026-03-30 11:55:15 +08:00
|
|
|
|
this->setAxisScale(axis_id, min, max);
|
|
|
|
|
|
if ( axis_id == QwtPlot::xBottom ) {
|
|
|
|
|
|
_init_x_min = min;
|
|
|
|
|
|
_init_x_max = max;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ( axis_id == QwtPlot::yLeft ) {
|
|
|
|
|
|
_init_y_min = min;
|
|
|
|
|
|
_init_y_max = max;
|
|
|
|
|
|
}
|
2026-03-13 15:36:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-30 11:55:15 +08:00
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::RegisterEventFilterFunc(std::function<bool (QObject *, QEvent *)> event_filter_func)
|
2026-03-13 15:36:08 +08:00
|
|
|
|
{
|
2026-03-30 11:55:15 +08:00
|
|
|
|
this->_event_filter_func_list.push_back(event_filter_func);
|
2026-03-13 15:36:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-30 11:55:15 +08:00
|
|
|
|
// void CustomQwtPlot::SetXaxisDragScale(bool enable)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// QwtScaleWidget *x_scale = axisWidget(QwtPlot::xBottom);
|
|
|
|
|
|
// x_scale->setMouseTracking(enable);
|
|
|
|
|
|
// x_scale->installEventFilter(enable ? this : nullptr);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
2026-03-13 15:36:08 +08:00
|
|
|
|
void CustomQwtPlot::ResetPlot()
|
|
|
|
|
|
{
|
|
|
|
|
|
this->setAxisScale(QwtPlot::xBottom, _init_x_min, _init_x_max);
|
|
|
|
|
|
this->setAxisScale(QwtPlot::yLeft, _init_y_min, _init_y_max);
|
|
|
|
|
|
this->replot();
|
2026-03-09 16:50:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 20:23:55 +08:00
|
|
|
|
QwtPlotCurve *CustomQwtPlot::GetCurve(const QString &curve_name)
|
2026-03-09 16:50:21 +08:00
|
|
|
|
{
|
2026-03-12 20:23:55 +08:00
|
|
|
|
return _curves.value(curve_name, nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QList<QwtPlotCurve *> CustomQwtPlot::GetCurveList() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return _curves.values();
|
2026-03-09 16:50:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-26 19:07:49 +08:00
|
|
|
|
void CustomQwtPlot::AddCurve(QwtPlotCurve *curve, bool auto_color)
|
2026-03-09 16:50:21 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (curve) {
|
2026-03-26 19:07:49 +08:00
|
|
|
|
if ( auto_color ) {
|
|
|
|
|
|
curve->setPen(QPen(getDistinctColorForManyCurves(_curves.count()), 1));
|
|
|
|
|
|
}
|
2026-03-18 19:31:24 +08:00
|
|
|
|
curve->setZ(0);
|
2026-03-09 16:50:21 +08:00
|
|
|
|
curve->attach(this);
|
2026-03-12 20:23:55 +08:00
|
|
|
|
_curves[curve->title().text()] = curve;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QwtPlotMarker *CustomQwtPlot::GetMarker(const QString &marker_name, const QString &postion)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _markers.value(marker_name).value(postion);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QList<QwtPlotMarker *> CustomQwtPlot::GetMarkerList() const
|
|
|
|
|
|
{
|
|
|
|
|
|
QList<QwtPlotMarker *> markers;
|
|
|
|
|
|
for (auto tmp_markers : this->_markers) {
|
|
|
|
|
|
markers.append(tmp_markers.values());
|
|
|
|
|
|
}
|
|
|
|
|
|
return markers;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::AddMarker(QwtPlotMarker *marker, const QString &marker_name, const QString &postion)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (marker) {
|
|
|
|
|
|
QwtPlotCurve* curve = GetCurve(marker_name);
|
|
|
|
|
|
if (curve) {
|
|
|
|
|
|
QPen pen = curve->pen();
|
|
|
|
|
|
pen.setWidth(2);
|
|
|
|
|
|
marker->setLinePen(pen);
|
2026-03-18 19:31:24 +08:00
|
|
|
|
marker->setZ(20);
|
2026-03-12 20:23:55 +08:00
|
|
|
|
marker->attach(this);
|
|
|
|
|
|
_markers[marker_name][postion] = marker;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::RemoveMarker(const QString &marker_name, const QString &postion)
|
|
|
|
|
|
{
|
|
|
|
|
|
QwtPlotMarker* marker = GetMarker(marker_name, postion);
|
|
|
|
|
|
if (marker) {
|
|
|
|
|
|
marker->detach();
|
|
|
|
|
|
delete marker;
|
|
|
|
|
|
}
|
|
|
|
|
|
_markers[marker_name].remove(postion);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::CleanMarkers()
|
|
|
|
|
|
{
|
|
|
|
|
|
QList<QwtPlotMarker *> markers = GetMarkerList();
|
|
|
|
|
|
for (auto marker : markers) {
|
|
|
|
|
|
if (marker) {
|
|
|
|
|
|
marker->detach();
|
|
|
|
|
|
delete marker;
|
|
|
|
|
|
}
|
2026-03-09 16:50:21 +08:00
|
|
|
|
}
|
2026-03-12 20:23:55 +08:00
|
|
|
|
this->_markers.clear();
|
2026-03-09 16:50:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-13 15:36:08 +08:00
|
|
|
|
QwtPlotZoneItem* CustomQwtPlot::GetZoneItem(const QString& zone_item_name)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _zone_items.value(zone_item_name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QList<QwtPlotZoneItem *> CustomQwtPlot::GetZoneItemList() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return this->_zone_items.values();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::AddZoneItem(QwtPlotZoneItem *zone_item, const QString &zone_item_name)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (zone_item) {
|
|
|
|
|
|
zone_item->setPen(Qt::transparent); // 无边框
|
|
|
|
|
|
zone_item->setBrush(QColor(0, 120, 215, 95)); // 半透明蓝色(RGBA:A=80 透明度)
|
2026-03-18 19:31:24 +08:00
|
|
|
|
zone_item->setZ(10);
|
2026-03-13 15:36:08 +08:00
|
|
|
|
zone_item->attach(this);
|
|
|
|
|
|
_zone_items[zone_item_name] = zone_item;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::RemoveZoneItem(const QString& zone_item_name)
|
|
|
|
|
|
{
|
|
|
|
|
|
QwtPlotZoneItem* zone_item = GetZoneItem(zone_item_name);
|
|
|
|
|
|
if (zone_item) {
|
|
|
|
|
|
zone_item->detach();
|
|
|
|
|
|
delete zone_item;
|
|
|
|
|
|
}
|
|
|
|
|
|
_zone_items.remove(zone_item_name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CustomQwtPlot::CleanZoneItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
QList<QwtPlotZoneItem *> zone_items = GetZoneItemList();
|
|
|
|
|
|
for (auto zone_item : zone_items) {
|
|
|
|
|
|
if (zone_item) {
|
|
|
|
|
|
zone_item->detach();
|
|
|
|
|
|
delete zone_item;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
this->_zone_items.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CustomQwtPlot::eventFilter(QObject *obj, QEvent *event)
|
|
|
|
|
|
{
|
2026-03-30 11:55:15 +08:00
|
|
|
|
bool has_filter = false;
|
|
|
|
|
|
for (auto filter : _event_filter_func_list) {
|
|
|
|
|
|
filter(obj, event);
|
|
|
|
|
|
has_filter = true;
|
2026-03-13 15:36:08 +08:00
|
|
|
|
}
|
2026-03-30 11:55:15 +08:00
|
|
|
|
if (has_filter) {
|
2026-03-13 15:36:08 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return QwtPlot::eventFilter(obj, event);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-30 11:55:15 +08:00
|
|
|
|
// void CustomQwtPlot::showEvent(QShowEvent *event)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Q_UNUSED(event);
|
|
|
|
|
|
// this->updateAxes();
|
|
|
|
|
|
// if ((0 == this->_init_x_max) && (0 == this->_init_y_max)) {
|
|
|
|
|
|
// // double x_min = this->axisScaleDiv(QwtPlot::xBottom).lowerBound();
|
|
|
|
|
|
// double x_max = this->axisScaleDiv(QwtPlot::xBottom).upperBound();
|
|
|
|
|
|
// // double y_min = this->axisScaleDiv(QwtPlot::yLeft).lowerBound();
|
|
|
|
|
|
// double y_max = this->axisScaleDiv(QwtPlot::yLeft).upperBound();
|
|
|
|
|
|
// this->_init_x_min = 0;
|
|
|
|
|
|
// this->_init_x_max = x_max;
|
|
|
|
|
|
// this->_init_y_min = 0;
|
|
|
|
|
|
// this->_init_y_max = y_max;
|
|
|
|
|
|
// this->setAxisScale(QwtPlot::xBottom, 0, x_max);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
2026-03-17 10:50:33 +08:00
|
|
|
|
|
2026-03-09 16:50:21 +08:00
|
|
|
|
QColor getDistinctColorForManyCurves(int curve_index)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 1. 定义基础色相(覆盖不同主色系,0-360度)
|
|
|
|
|
|
const QList<int> base_hues = {
|
|
|
|
|
|
0, // 红色
|
|
|
|
|
|
30, // 橙色
|
|
|
|
|
|
60, // 黄色
|
|
|
|
|
|
90, // 黄绿色
|
|
|
|
|
|
120, // 绿色
|
|
|
|
|
|
150, // 青绿色
|
|
|
|
|
|
180, // 青色
|
|
|
|
|
|
210, // 天蓝色
|
|
|
|
|
|
240, // 蓝色
|
|
|
|
|
|
270, // 紫色
|
|
|
|
|
|
300, // 洋红色
|
|
|
|
|
|
330 // 玫红色
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 定义不同的饱和度/明度组合(避免颜色太暗/太灰)
|
|
|
|
|
|
const QList<QPair<int, int>> sv_combinations = {
|
|
|
|
|
|
{85, 90}, // 高饱和、高明度
|
|
|
|
|
|
{70, 85}, // 中高饱和、中高明度
|
|
|
|
|
|
{85, 75}, // 高饱和、中明度
|
|
|
|
|
|
{60, 80}, // 中饱和、中高明度
|
|
|
|
|
|
{75, 70}, // 中高饱和、中明度
|
|
|
|
|
|
{90, 80} // 极高饱和、中高明度
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 计算当前曲线对应的色相和饱和度/明度
|
|
|
|
|
|
int hue_index = curve_index % base_hues.size(); // 循环使用基础色相
|
|
|
|
|
|
int sv_index = (curve_index / base_hues.size()) % sv_combinations.size(); // 循环使用饱和度/明度组合
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 获取HSV参数(色相0-360,饱和度0-255,明度0-255)
|
|
|
|
|
|
int hue = base_hues[hue_index];
|
|
|
|
|
|
int saturation = sv_combinations[sv_index].first * 255 / 100; // 转换为0-255范围
|
|
|
|
|
|
int value = sv_combinations[sv_index].second * 255 / 100; // 转换为0-255范围
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 生成并返回颜色(HSV转RGB)
|
|
|
|
|
|
QColor color;
|
|
|
|
|
|
color.setHsv(hue, saturation, value);
|
|
|
|
|
|
|
|
|
|
|
|
// 额外优化:避免极浅/极暗的颜色(保证曲线可见)
|
|
|
|
|
|
if (value < 50 * 255 / 100) {
|
|
|
|
|
|
value = 50 * 255 / 100;
|
|
|
|
|
|
color.setHsv(hue, saturation, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return color;
|
|
|
|
|
|
}
|
|
|
|
|
|
|