一、效果

二、代码
#include "obsersingle.h"
#include "ui_obsersingle.h"
#pragma execution_character_set("utf-8")
void ObserSingle::RescaleActionFun::fun(ObserSingle *form)
{form->customPlot->rescaleAxes(true);form->customPlot->replot(QCustomPlot::rpQueuedReplot);
}
void ObserSingle::CursorActionFun::fun(ObserSingle *form)
{if(form->cursorShow){form->lineY->point1->setCoords(0, 0);form->lineY->point2->setCoords(0, 0);form->lineX->point1->setCoords(0, 0);form->lineX->point2->setCoords(0, 0);form->cursorShow = false;}else{form->cursorShow = true;}form->customPlot->replot(QCustomPlot::rpQueuedReplot);
}
ObserSingle::ObserSingle(QWidget *parent) :QWidget(parent),ui(new Ui::ObserSingle), clickMenu(new QMenu), lineY(nullptr), lineX(nullptr), cursorShow(false), midButtonPress(false), customPlot(new QCustomPlot)
{ui->setupUi(this);QGridLayout *layout = new QGridLayout();layout->setContentsMargins(2, 2, 2, 2);layout->addWidget(customPlot);ui->plotWindow->setLayout(layout);customPlot->xAxis->setRange(1, 1, Qt::AlignRight); customPlot->xAxis->ticker()->setTickCount(8); customPlot->xAxis->setLabel(tr("xAxis")); customPlot->yAxis->setRange(2, 2, Qt::AlignRight);customPlot->yAxis->ticker()->setTickCount(5);customPlot->yAxis->setLabel(tr("yAxis"));customPlot->legend->setVisible(true); customPlot->legend->setBrush(QColor(255, 255, 255, 50)); customPlot->legend->setBorderPen(Qt::NoPen); customPlot->legend->setWrap(4); customPlot->legend->setFillOrder(QCPLayoutGrid::foRowsFirst);
customPlot->plotLayout()->setRowStretchFactor(0, 0.001); customPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables);
customPlot->legend->setSelectableParts(QCPLegend::spItems);QObject::connect(customPlot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));clickMenuAddAction(tr("适应窗口大小"), ":/reference/image/plot.png", new RescaleActionFun);clickMenuAddAction(tr("十字游标"), ":/reference/image/plot.png", new CursorActionFun);QObject::connect(customPlot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(onMousePress(QMouseEvent *)));lineY = new QCPItemStraightLine(customPlot);lineY->setLayer("overlay");lineY->setPen(QPen(Qt::gray, 1, Qt::DashLine));lineY->setClipToAxisRect(true);lineY->point1->setCoords(0, 0);lineY->point2->setCoords(0, 0);lineX = new QCPItemStraightLine(customPlot);lineX->setLayer("overlay");lineX->setPen(QPen(Qt::gray, 1, Qt::DashLine));lineX->setClipToAxisRect(true);lineX->point1->setCoords(0, 0);lineX->point2->setCoords(0, 0);QObject::connect(customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(onMouseMove(QMouseEvent *)));QObject::connect(customPlot, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(onMouseRelease(QMouseEvent *)));customPlot->rescaleAxes(true);customPlot->replot(QCustomPlot::rpQueuedReplot);
}ObserSingle::~ObserSingle()
{ui->plotWindow->layout()->deleteLater();QList<QString> keyList = actionFunMap.keys();for(int i=0; i<keyList.size(); i++){if(actionFunMap[keyList[i]]){delete actionFunMap[keyList[i]];}}QList<QAction *> actionList = actionMap.keys();for(int i=0; i<actionList.size(); i++){if(actionList.at(i)){delete actionList.at(i);}}if(clickMenu){clickMenu->deleteLater();}if(customPlot){customPlot->deleteLater();}delete ui;
}
void ObserSingle::onMouseMove(QMouseEvent *event)
{if(midButtonPress){QPoint pos = QCursor::pos();int xLen = pos.x() - posPress.x();int yLen = pos.y() - posPress.y();if(qAbs(xLen) - qAbs(yLen) > 0){if(xLen > 0){double xSize = customPlot->xAxis->range().upper - customPlot->xAxis->range().lower;customPlot->xAxis->setRangeLower(customPlot->xAxis->range().lower + xSize/20);customPlot->xAxis->setRangeUpper(customPlot->xAxis->range().upper - xSize/20);}else{double xSize = customPlot->xAxis->range().upper - customPlot->xAxis->range().lower;customPlot->xAxis->setRangeLower(customPlot->xAxis->range().lower - xSize/20);customPlot->xAxis->setRangeUpper(customPlot->xAxis->range().upper + xSize/20);}}else{if(yLen > 0){double ySize = customPlot->yAxis->range().upper - customPlot->yAxis->range().lower;customPlot->yAxis->setRangeLower(customPlot->yAxis->range().lower - ySize/20);customPlot->yAxis->setRangeUpper(customPlot->yAxis->range().upper + ySize/20);}else{double ySize = customPlot->yAxis->range().upper - customPlot->yAxis->range().lower;customPlot->yAxis->setRangeLower(customPlot->yAxis->range().lower + ySize/20);customPlot->yAxis->setRangeUpper(customPlot->yAxis->range().upper - ySize/20);}}posPress = pos;customPlot->replot(QCustomPlot::rpQueuedReplot);}else{int x_pos = event->pos().x();int y_pos = event->pos().y();float x_val = customPlot->xAxis->pixelToCoord(x_pos);float y_val = customPlot->yAxis->pixelToCoord(y_pos);if(cursorShow){lineY->point1->setCoords(x_val, customPlot->yAxis->range().lower);lineY->point2->setCoords(x_val, customPlot->yAxis->range().upper);lineX->point1->setCoords(customPlot->xAxis->range().lower, y_val);lineX->point2->setCoords(customPlot->xAxis->range().upper, y_val);customPlot->replot(QCustomPlot::rpQueuedReplot);}QToolTip::hideText();QToolTip::showText(event->globalPos(),QString("x:%1 y:%2").arg(x_val).arg(y_val),this, rect());}
}
void ObserSingle::selectionChanged()
{if (customPlot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels)){customPlot->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);customPlot->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);}if (customPlot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || customPlot->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels)){customPlot->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);customPlot->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);}for (int i=0; i<customPlot->graphCount(); ++i){QCPGraph *graph = customPlot->graph(i);QCPPlottableLegendItem *item = customPlot->legend->itemWithPlottable(graph);if (item->selected() || graph->selected()){item->setSelected(true);graph->setSelection(QCPDataSelection(graph->data()->dataRange()));}}
}
void ObserSingle::onMousePress(QMouseEvent *event)
{if(event->button() == Qt::RightButton){clickMenu->exec(QCursor::pos());}else if(event->button() == Qt::MiddleButton){midButtonPress = true;posPress = QCursor::pos();}
}
void ObserSingle::onMouseRelease(QMouseEvent *event)
{if(event->button() == Qt::MiddleButton){midButtonPress = false;}
}
void ObserSingle::_on_action_create_triggered(void)
{QAction *action = static_cast<QAction *>(this->sender());if(actionMap.contains(action)){if(actionFunMap.contains(actionMap[action])){actionFunMap[actionMap[action]]->fun(this);}}
}
void ObserSingle::clickMenuAddAction(QString name, QString icon, MenuActionFun *fun)
{QAction *action = new QAction(QIcon(icon), name, this);actionMap.insert(action, name);QObject::connect(action, SIGNAL(triggered()), this, SLOT(_on_action_create_triggered()));clickMenu->addAction(action);actionFunMap.insert(name, fun);
}
void ObserSingle::drawCurve(const QString name, const QVector<double> x, const QVector<double> y, QPen pen)
{if(curveMap.contains(name)){curveMap[name]->setData(x, y, true);}else{QCPGraph *graph = customPlot->addGraph();graph->setAntialiased(false); graph->setAntialiasedFill(false);graph->setAntialiasedScatters(false);graph->setPen(pen);graph->setName(name);graph->setData(x, y, true);curveMap.insert(name, graph);}customPlot->replot(QCustomPlot::rpQueuedReplot);
}
void ObserSingle::clearCurve(const QString name)
{if(curveMap.contains(name)){QVector<double> x, y;
QCPGraph *graph;curveMap.remove(name);QList<QString> nameList = curveMap.keys();QList<QString> nameListSave;QList<QVector<double>> xList;QList<QVector<double>> yList;QList<QPen> penList;for(int i=0; i<nameList.size(); i++){graph = curveMap[nameList[i]];curveMap.remove(nameList[i]);x.clear();y.clear();for(int data_i=0; data_i<graph->data()->size(); data_i++){x.append(graph->data()->at(data_i)->key);y.append(graph->data()->at(data_i)->value);}QColor color = graph->pen().color();
nameListSave.append(nameList[i]);xList.append(x);yList.append(y);penList.append(QPen(color));}customPlot->clearGraphs();for(int i=0; i<nameListSave.size(); i++){drawCurve(nameListSave[i], xList[i], yList[i], penList[i]);}}customPlot->replot(QCustomPlot::rpQueuedReplot);
}
void ObserSingle::replot(void)
{customPlot->rescaleAxes(true);
}
void ObserSingle::setRunStatus(bool b)
{if(b){customPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes );for (int i=0; i<customPlot->graphCount(); ++i){QCPGraph *graph = customPlot->graph(i);QCPPlottableLegendItem *item = customPlot->legend->itemWithPlottable(graph);if (item->selected() || graph->selected()){item->setSelected(false);QCPDataSelection select;graph->setSelection(select);}}}else{customPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom| QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables);}
}