#include "CustomQwtPlot.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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(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); } CustomQwtPlot::CustomQwtPlot(QWidget *parent) : QwtPlot(parent) { } CustomQwtPlot::~CustomQwtPlot() { qDebug() << "~CustomQwtPlot"; } 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) { 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; } } void CustomQwtPlot::RegisterEventFilterFunc(std::function event_filter_func) { this->_event_filter_func_list.push_back(event_filter_func); } // void CustomQwtPlot::SetXaxisDragScale(bool enable) // { // QwtScaleWidget *x_scale = axisWidget(QwtPlot::xBottom); // x_scale->setMouseTracking(enable); // x_scale->installEventFilter(enable ? this : nullptr); // } 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(); } QwtPlotCurve *CustomQwtPlot::GetCurve(const QString &curve_name) { return _curves.value(curve_name, nullptr); } QList CustomQwtPlot::GetCurveList() const { return _curves.values(); } void CustomQwtPlot::AddCurve(QwtPlotCurve *curve, bool auto_color) { if (curve) { if ( auto_color ) { curve->setPen(QPen(getDistinctColorForManyCurves(_curves.count()), 1)); } curve->setZ(0); curve->attach(this); _curves[curve->title().text()] = curve; } } QwtPlotMarker *CustomQwtPlot::GetMarker(const QString &marker_name, const QString &postion) { return _markers.value(marker_name).value(postion); } QList CustomQwtPlot::GetMarkerList() const { QList 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); marker->setZ(20); 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 markers = GetMarkerList(); for (auto marker : markers) { if (marker) { marker->detach(); delete marker; } } this->_markers.clear(); } QwtPlotZoneItem* CustomQwtPlot::GetZoneItem(const QString& zone_item_name) { return _zone_items.value(zone_item_name); } QList 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 透明度) zone_item->setZ(10); 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 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) { bool has_filter = false; for (auto filter : _event_filter_func_list) { filter(obj, event); has_filter = true; } if (has_filter) { return true; } return QwtPlot::eventFilter(obj, event); } // 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); // } // } QColor getDistinctColorForManyCurves(int curve_index) { // 1. 定义基础色相(覆盖不同主色系,0-360度) const QList base_hues = { 0, // 红色 30, // 橙色 60, // 黄色 90, // 黄绿色 120, // 绿色 150, // 青绿色 180, // 青色 210, // 天蓝色 240, // 蓝色 270, // 紫色 300, // 洋红色 330 // 玫红色 }; // 2. 定义不同的饱和度/明度组合(避免颜色太暗/太灰) const QList> 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; }