#include "VCustomPlot.h" //#include #include "GvlManager.h" // 默认的分块数 #define DEFAULT_CUSTOMPLOT_COUNT 3 VCustomPlot::VCustomPlot( QWidget* parent, const QPoint& pos, const QSize& size, CONTROL_PROPERTY* pProperty, CONTROL_PROPERTY_EX* pPropertyEx ) : QWidget(parent) , VControlObject(pProperty) { // 设置控件指针 m_pWidget = this; // 设置控件类型 m_Type = VALUE_TYPE::Control_CustomPlot; //实例化曲线控件 customPlot = new QCustomPlot; //绑定鼠标移动显示数据 connect(customPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove(QMouseEvent*))); layerable = 0; tracer = 0; textTip = 0; //设置布局加入曲线控件 QHBoxLayout* layout = new QHBoxLayout; layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(customPlot); this->setLayout(layout); //备用颜色集合 setColorNames(CustomPlotHelper::getColorNames().join("|")); setBgColor(QColor(38, 41, 74)); setBgColor(QColor(61, 61, 61)); setTextColor(QColor(250, 250, 250)); gridWidth = 1; setGridColor(QColor(230, 230, 230)); lineWidth = 3; lineColor = QColor(255, 0, 0); showLineh = false; showLinev = false; fontSize = 12; pointSize = 8; offsetX = 1; offsetY = 20; toolTipPosition = 0; interactions = 0; padding = 5; axis2Visible = false; percentY = false; isLoad = false; this->init(); //if (parent == nullptr) //{ // return; //} // 作为控件时候的专用初始化代码。 ////////////////////////////////////////////////////////////////////////// // 设置尺寸 if (size == DEFAULT_CONTROL_SIZE) { this->resize(DEFAULT_IMAGE_SIZE); } else { this->resize(size); } // 设置中心点坐标 QPoint tempPos; tempPos.setX(pos.x() - width() / 2); tempPos.setY(pos.y() - height() / 2); // 设置位置 this->move(tempPos); initPropertyEx(pPropertyEx); //customPlot->axisRect()->setupFullAxesBox();//四边安装轴并显示 //自定义属性在此从属性表中设置到控件 { setInteractions(m_Property.m_nInteractions); setDrawingMode(m_Property.m_nDrawingMode); setText(m_Property.m_strText); } } void VCustomPlot::showEvent(QShowEvent*) { if (!isLoad) { isLoad = true; if (this->showLineh || this->showLinev) { this->drawFlowLine(); } } } void VCustomPlot::resizeEvent(QResizeEvent*) { if (layerable != 0) { layerable->drawLine(); } } void VCustomPlot::mouseMove(QMouseEvent* event) { if (tracer == 0 || textTip == 0) { return; } //跟踪鼠标点击事件点击位置 QCPGraph* graph = (QCPGraph*)customPlot->plottableAt(event->pos(), true); QRect rect(0, 0, 1, 1); QString labx, laby; int offset = 10; bool toolTip = false; if (graph != 0) { double posKey; double key = 0, value = 0; QPoint p; p.setX(event->pos().x()); p.setY(event->pos().y()); #ifdef qcustomplot_v1 foreach(QCPData data, graph->data()->values()) { key = data.key; value = data.value; #else for (int i = 0; i < graph->dataCount(); i++) { key = graph->dataMainKey(i); value = graph->dataMainValue(i); #endif //取出对应key处的label标签,如果标签为空则取key的字符串 //需要根据tickVector来找到对应的tickVectorLabels,有时候拖动表到不可见的部位tickVectorLabels不是全部的tickVectorLabels vdouble values = customPlot->xAxis->tickVector(); vstring labs = customPlot->xAxis->tickVectorLabels(); int index = values.indexOf(key); if (index >= 0 && labs.size() > 0) { labx = labs.at(index); } else { labx = QString::number(key); } //如果启用了百分比则需要后面显示百分比 if (this->getPercentY()) { laby = QString("%1%").arg(value); } else { laby = QString("%1").arg(value); } //计算当前是否在区域内,在的话就显示 posKey = customPlot->xAxis->coordToPixel(key); if (qAbs(posKey - event->pos().x()) <= offset) { double posx = graph->keyAxis()->coordToPixel(key); double posy = graph->valueAxis()->coordToPixel(value); rect.setRect(posx - offset, posy - offset, offset * 2, offset * 2); if (!rect.contains(event->pos())) { continue; } else { break; } } if (posKey - event->pos().x() > offset) { break; } } if (!graph->realVisibility()) { toolTip = false; tracer->setVisible(false); customPlot->replot(); } else if (rect.contains(event->pos())) { //先设置大小和颜色 tracer->setSize(10); tracer->setPen(QPen(this->m_Property.m_clrText, 3)); tracer->setBrush(QBrush(lineColor, Qt::SolidPattern)); toolTip = true; tracer->setVisible(true); tracer->setGraph(graph); tracer->setGraphKey(key); customPlot->replot(); } else if (tracer->visible()) { toolTip = false; tracer->setVisible(false); customPlot->replot(); } } else if (tracer->visible()) { toolTip = false; tracer->setVisible(false); customPlot->replot(); } //处理提示信息 if (toolTip) { //根据设定的提示信息位置调整 double x = event->pos().x(); double y = event->pos().y(); checkToolTip(x, y); //先设置颜色 textTip->setColor(this->m_Property.m_clrText); textTip->setBrush(this->m_Property.m_clrBg); QString text = "横坐标: " + labx + "\n当前值: " + laby; textTip->position->setCoords(x, y); textTip->setText(text); textTip->setVisible(true); customPlot->replot(); } else { if (textTip->visible()) { textTip->setVisible(false); customPlot->replot(); } } } void VCustomPlot::checkToolTip(double& x, double& y) { //下面的计算位置偏移值未必精准可以自行调整 //后期可能要根据提示信息面板的宽高进行精准计算 if (toolTipPosition == 0) { //判断曲线控件的位置已经当前鼠标位置做出调整 bool right = (customPlot->width() - x < 90); bool bottom = (customPlot->height() - y < 50); if (right) { if (bottom) { x = x - 100; y = y - 50; } else { x = x - 100; y = y + 10; } } else { if (bottom) { x = x + 10; y = y - 50; } else { x = x + 10; y = y + 10; } } } else if (toolTipPosition == 1) { x = x - 30; y = y - 50; } else if (toolTipPosition == 2) { x = x + 10; y = y - 50; } else if (toolTipPosition == 3) { x = x + 10; y = y - 20; } else if (toolTipPosition == 4) { x = x + 10; y = y + 10; } else if (toolTipPosition == 5) { x = x - 30; y = y + 10; } else if (toolTipPosition == 6) { x = x - 75; y = y + 10; } else if (toolTipPosition == 7) { x = x - 80; y = y - 20; } else if (toolTipPosition == 8) { x = x - 80; y = y - 50; } } lcolor VCustomPlot::getColors() const { return this->colors; } QString VCustomPlot::getColorNames() const { return this->colorNames; } QColor VCustomPlot::getBgColor() const { return this->m_Property.m_clrBg; } QColor VCustomPlot::getTextColor() const { return this->m_Property.m_clrText; } int VCustomPlot::getGridWidth() const { return this->gridWidth; } QColor VCustomPlot::getGridColor() const { return this->gridColor; } int VCustomPlot::getLineWidth() const { return this->lineWidth; } QColor VCustomPlot::getLineColor() const { return this->lineColor; } bool VCustomPlot::getShowLineh() const { return this->showLineh; } bool VCustomPlot::getShowLinev() const { return this->showLinev; } int VCustomPlot::getFontSize() const { return this->fontSize; } int VCustomPlot::getPointSize() const { return this->pointSize; } double VCustomPlot::getOffsetX() const { return this->offsetX; } double VCustomPlot::getOffsetY() const { return this->offsetY; } int VCustomPlot::getToolTipPosition() const { return this->toolTipPosition; } int VCustomPlot::getInteractions() const { return this->interactions; } int VCustomPlot::getDrawingMode() const { return this->m_Property.m_nDrawingMode; } int VCustomPlot::getTickCountX() const { return this->m_Property.m_nTickCountX; } int VCustomPlot::getTickCountY() const { return this->m_Property.m_nTickCountY; } QSize VCustomPlot::getRangeX()const { return this->m_Property.m_RangeX; } QSize VCustomPlot::getRangeY()const { return this->m_Property.m_RangeY; } int VCustomPlot::getPadding() const { return this->padding; } bool VCustomPlot::getAxis2Visible() const { return this->axis2Visible; } bool VCustomPlot::getPercentY() const { return this->percentY; } QSize VCustomPlot::sizeHint() const { return QSize(500, 350); } QSize VCustomPlot::minimumSizeHint() const { return QSize(50, 35); } QCustomPlot* VCustomPlot::getPlot() const { return this->customPlot; } void VCustomPlot::setText(const QString & title) { this->m_Property.m_strText = title; customPlot->yAxis->setLabel(title); //重新刷新显示 this->replot(); } void VCustomPlot::setColorNames(const QString & colorNames) { //数量小于原来的则依次替换 QStringList names = colorNames.split("|"); QStringList names2 = this->colorNames.split("|"); int count = names.count(); if (count < colors.count()) { for (int i = 0; i < count; ++i) { names2[i] = names.at(i); } this->colorNames = names2.join("|"); } else { this->colorNames = colorNames; } //重新替换颜色集合 colors.clear(); names = this->colorNames.split("|"); foreach(QString name, names) { colors << name; } } void VCustomPlot::setBgColor(const QColor & bgColor) { if (this->m_Property.m_clrBg != bgColor) { this->m_Property.m_clrBg = bgColor; customPlot->setBackground(bgColor); customPlot->axisRect()->setBackground(bgColor); customPlot->replot(); // 刷新 this->replot(); } } void VCustomPlot::setTextColor(const QColor & textColor) { if (this->m_Property.m_clrText != textColor) { this->m_Property.m_clrText = textColor; scatterStyle.setSize(pointSize); scatterStyle.setPen(QPen(textColor, 2)); scatterStyle.setShape(QCPScatterStyle::ssCircle); customPlot->legend->setTextColor(textColor); customPlot->replot(); } } void VCustomPlot::setGridWidth(int gridWidth) { if (this->gridWidth != gridWidth) { this->gridWidth = gridWidth; } } void VCustomPlot::setGridColor(const QColor & gridColor) { if (this->gridColor != gridColor) { this->gridColor = gridColor; QPen pen(gridColor, gridWidth); //第一坐标轴 customPlot->xAxis->setLabelColor(gridColor); customPlot->yAxis->setLabelColor(gridColor); customPlot->xAxis->setTickLabelColor(gridColor); customPlot->yAxis->setTickLabelColor(gridColor); customPlot->xAxis->setBasePen(pen); customPlot->yAxis->setBasePen(pen); customPlot->xAxis->setTickPen(pen); customPlot->yAxis->setTickPen(pen); customPlot->xAxis->setSubTickPen(pen); customPlot->yAxis->setSubTickPen(pen); customPlot->xAxis->grid()->setPen(pen); customPlot->yAxis->grid()->setPen(pen); customPlot->xAxis->grid()->setZeroLinePen(pen); customPlot->yAxis->grid()->setZeroLinePen(pen); //第二坐标轴 customPlot->xAxis2->setLabelColor(gridColor); customPlot->yAxis2->setLabelColor(gridColor); customPlot->xAxis2->setTickLabelColor(gridColor); customPlot->yAxis2->setTickLabelColor(gridColor); customPlot->xAxis2->setBasePen(pen); customPlot->yAxis2->setBasePen(pen); customPlot->xAxis2->setTickPen(pen); customPlot->yAxis2->setTickPen(pen); customPlot->xAxis2->setSubTickPen(pen); customPlot->yAxis2->setSubTickPen(pen); customPlot->xAxis2->grid()->setPen(pen); customPlot->yAxis2->grid()->setPen(pen); customPlot->xAxis2->grid()->setZeroLinePen(pen); customPlot->yAxis2->grid()->setZeroLinePen(pen); customPlot->replot(); } } void VCustomPlot::setLineWidth(int lineWidth) { if (this->lineWidth != lineWidth && layerable != 0) { this->lineWidth = lineWidth; layerable->setLineWidth(lineWidth); } } void VCustomPlot::setLineColor(const QColor & lineColor) { if (this->lineColor != lineColor && layerable != 0) { this->lineColor = lineColor; layerable->setLineColor(lineColor); } } void VCustomPlot::setShowLineh(bool showLineh) { if (this->showLineh != showLineh && layerable != 0) { this->showLineh = showLineh; layerable->setShowLineh(showLineh); } } void VCustomPlot::setShowLinev(bool showLinev) { if (this->showLinev != showLinev && layerable != 0) { this->showLinev = showLinev; layerable->setShowLinev(showLinev); } } void VCustomPlot::setFontSize(int fontSize) { if (this->fontSize != fontSize) { this->fontSize = fontSize; QFont font; font.setPixelSize(fontSize); customPlot->legend->setFont(font); customPlot->xAxis->setLabelFont(font); customPlot->yAxis->setLabelFont(font); customPlot->xAxis->setTickLabelFont(font); customPlot->yAxis->setTickLabelFont(font); customPlot->xAxis2->setLabelFont(font); customPlot->yAxis2->setLabelFont(font); customPlot->xAxis2->setTickLabelFont(font); customPlot->yAxis2->setTickLabelFont(font); customPlot->replot(); } } void VCustomPlot::setPointSize(int pointSize) { if (this->pointSize != pointSize) { this->pointSize = pointSize; customPlot->replot(); } } void VCustomPlot::setOffsetX(double offsetX) { if (this->offsetX != offsetX) { this->offsetX = offsetX; } } void VCustomPlot::setOffsetY(double offsetY) { if (this->offsetY != offsetY) { this->offsetY = offsetY; } } void VCustomPlot::setToolTipPosition(int toolTipPosition) { if (this->toolTipPosition != toolTipPosition) { this->toolTipPosition = toolTipPosition; customPlot->replot(); } } void VCustomPlot::setInteractions(int interactions) { if (this->interactions != interactions) { this->interactions = interactions; if (interactions == 0) {// 所有对象都可选 customPlot->setInteractions(QCP::iSelectOther); } else if (interactions == 1) { customPlot->setInteractions(QCP::iRangeDrag); } else if (interactions == 2) { customPlot->setInteractions(QCP::iRangeZoom); } else if (interactions == 3) { customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); } else { customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iMultiSelect | QCP::iSelectPlottables | QCP::iSelectAxes); } } m_Property.m_nInteractions = interactions; // qDebug() << interactions; } void VCustomPlot::setDrawingMode(int nMode) { switch (nMode) { case 0: { for (int i = 0; i < customPlot->graphCount(); i++) { customPlot->graph(i)->setLineStyle(QCPGraph::LineStyle::lsLine); } } break; case 1: { for (int i = 0; i < customPlot->graphCount(); i++) { customPlot->graph(i)->setLineStyle(QCPGraph::LineStyle::lsStepLeft); } } break; case 2: { for (int i = 0; i < customPlot->graphCount(); i++) { customPlot->graph(i)->setLineStyle(QCPGraph::LineStyle::lsStepRight); } } break; case 3: { for (int i = 0; i < customPlot->graphCount(); i++) { customPlot->graph(i)->setLineStyle(QCPGraph::LineStyle::lsImpulse); } } break; case 4: { for (int i = 0; i < customPlot->graphCount(); i++) { customPlot->graph(i)->setLineStyle(QCPGraph::LineStyle::lsStepCenter); } } break; default: { for (int i = 0; i < customPlot->graphCount(); i++) { customPlot->graph(i)->setLineStyle(QCPGraph::LineStyle::lsLine); } } break; } m_Property.m_nDrawingMode = nMode; // // 刷新 // this->replot(); } void VCustomPlot::setTickCountX(int nTickCount) { m_Property.m_nTickCountX = nTickCount; customPlot->xAxis->ticker()->setTickCount(nTickCount); // 刷新 this->replot(); } void VCustomPlot::setTickCountY(int nTickCount) { m_Property.m_nTickCountY = nTickCount; customPlot->yAxis->ticker()->setTickCount(nTickCount); // 刷新 this->replot(); } void VCustomPlot::setRangeX(QSize RangeX) { m_Property.m_RangeX = RangeX; customPlot->xAxis->setRange(RangeX.width(), RangeX.height()); // 刷新 this->replot(); } void VCustomPlot::setRangeY(QSize RangeY) { m_Property.m_RangeY = RangeY; customPlot->yAxis->setRange(RangeY.width(), RangeY.height()); // 刷新 this->replot(); } void VCustomPlot::setPadding(int padding) { if (this->padding != padding) { this->padding = padding; customPlot->xAxis->setPadding(padding); customPlot->yAxis->setPadding(padding); customPlot->xAxis2->setPadding(padding); customPlot->yAxis2->setPadding(padding); customPlot->xAxis2->setOffset(25); } } void VCustomPlot::setAxis2Visible(bool axis2Visible) { if (this->axis2Visible != axis2Visible) { this->axis2Visible = axis2Visible; //设置第二坐标轴是否显示,可以形成闭合的盒子 customPlot->xAxis2->setVisible(axis2Visible); customPlot->yAxis2->setVisible(axis2Visible); customPlot->xAxis2->setTicks(false); customPlot->yAxis2->setTicks(false); customPlot->xAxis2->setTickLabels(false); customPlot->yAxis2->setTickLabels(false); } } void VCustomPlot::setPercentY(bool percentY) { if (this->percentY != percentY) { this->percentY = percentY; } } void VCustomPlot::setLegend(bool visible, int position, int column) { customPlot->legend->setVisible(visible); #ifndef qcustomplot_v1 customPlot->legend->setWrap(column); //设置摆放位置顺序列优先,这样的话就是一行,默认是一列垂直分布 customPlot->legend->setFillOrder(QCPLayoutGrid::FillOrder::foColumnsFirst); #endif QCPLayoutInset* layout = customPlot->axisRect()->insetLayout(); if (position == 0) { layout->setInsetAlignment(0, Qt::AlignTop | Qt::AlignHCenter); } else if (position == 1) { layout->setInsetAlignment(0, Qt::AlignTop | Qt::AlignRight); } else if (position == 2) { layout->setInsetAlignment(0, Qt::AlignVCenter | Qt::AlignRight); } else if (position == 3) { layout->setInsetAlignment(0, Qt::AlignBottom | Qt::AlignRight); } else if (position == 4) { layout->setInsetAlignment(0, Qt::AlignBottom | Qt::AlignHCenter); } else if (position == 5) { layout->setInsetAlignment(0, Qt::AlignBottom | Qt::AlignLeft); } else if (position == 6) { layout->setInsetAlignment(0, Qt::AlignVCenter | Qt::AlignLeft); } else if (position == 7) { layout->setInsetAlignment(0, Qt::AlignTop | Qt::AlignLeft); } } void VCustomPlot::setVisible(int index, bool visible) { //画布的数量一定小于等于画布索引 if (customPlot->graphCount() <= index) { return; } customPlot->graph(index)->setVisible(visible); customPlot->legend->elementAt(index)->setVisible(visible); } void VCustomPlot::init() { #ifdef qcustomplot_v1 #if 0 customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime); customPlot->xAxis->setDateTimeFormat("mm:ss"); customPlot->xAxis->setAutoTicks(false); customPlot->xAxis->setAutoTickLabels(false); customPlot->xAxis->setAutoTickStep(false); customPlot->xAxis->setTickStep(1); customPlot->yAxis->setAutoTicks(false); customPlot->yAxis->setAutoTickLabels(false); customPlot->yAxis->setAutoTickStep(false); customPlot->yAxis->setTickStep(1); #endif #endif //设置图例 customPlot->legend->setVisible(false); customPlot->legend->setBrush(QColor(255, 255, 255, 10)); customPlot->legend->setBorderPen(Qt::NoPen); //设置网格线可见 customPlot->xAxis->grid()->setVisible(true); customPlot->yAxis->grid()->setVisible(true); //设置子网格线可见 //customPlot->xAxis->grid()->setSubGridVisible(true); //customPlot->yAxis->grid()->setSubGridVisible(true); //设置网格线伸出部分 customPlot->xAxis->setTickLength(0, 0); //customPlot->yAxis->setTickLength(0, 0); //设置子网格伸出部分 customPlot->xAxis->setSubTickLength(0, 0); //customPlot->yAxis->setSubTickLength(0, 0); customPlot->xAxis->setVisible(true); customPlot->setInteractions(QCP::iSelectOther); customPlot->replot(); } void VCustomPlot::initTracer() { if (layerable != 0) { return; } //增加一个层用于绘制游标 layerable = new CustomPlotTracer(customPlot); layerable->setVisible(true); } void VCustomPlot::initItem() { if (tracer != 0 || textTip != 0) { return; } //增加数据点指示器高亮显示数据点 tracer = new QCPItemTracer(customPlot); tracer->setParent(customPlot); tracer->setStyle(QCPItemTracer::tsCircle); tracer->setVisible(false); //增加数据点提示信息 textTip = new QCPItemText(customPlot); textTip->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); textTip->setPositionAlignment(Qt::AlignLeft); textTip->position->setType(QCPItemPosition::PositionType::ptAbsolute); textTip->setPadding(QMargins(6, 6, 6, 6)); textTip->setVisible(false); } void VCustomPlot::clearData(int index) { //画布的数量一定小于等于画布索引 if (customPlot->graphCount() <= index) { return; } #ifdef qcustomplot_v1 customPlot->graph(index)->clearData(); #else customPlot->graph(index)->data().clear(); #endif } void VCustomPlot::clear(bool clearGraphs, bool clearItems, bool clearPlottables) { if (clearGraphs) { customPlot->clearGraphs(); } if (clearItems) { customPlot->clearItems(); tracer = 0; textTip = 0; } if (clearPlottables) { customPlot->clearPlottables(); } } void VCustomPlot::replot(QCustomPlot::RefreshPriority refreshPriority) { customPlot->replot(refreshPriority); } void VCustomPlot::drawFlowLine() { if (layerable != 0) { layerable->drawLine(); customPlot->replot(); } } void VCustomPlot::drawStaticLinev(double x, double y, const QColor & color, int width) { if (staticBarv == 0) { staticBarv = new QCPBars(customPlot->xAxis, customPlot->yAxis); } //用柱状图形式绘制线条 staticBarv->setWidth(width); staticBarv->setWidthType(QCPBars::wtAbsolute); staticBarv->setPen(color); staticBarv->setBrush(color); staticBarv->setData(vdouble() << x, vdouble() << y); } void VCustomPlot::drawStaticLineh(double x, double y, const QColor & color, int width) { if (staticBarv == 0) { staticBarv = new QCPBars(customPlot->xAxis, customPlot->yAxis); } //用柱状图形式绘制线条 staticBarv->setWidth(width); staticBarv->setWidthType(QCPBars::wtAbsolute); staticBarv->setPen(color); staticBarv->setBrush(color); staticBarv->setData(vdouble() << x, vdouble() << y); } QColor VCustomPlot::getRandColor() { return CustomPlotHelper::getRandColor(); } void VCustomPlot::addGraph(int count) { for (int i = 0; i < count; i++) { customPlot->addGraph(); } } void VCustomPlot::initUI(QString strXName, QString strYName) { //设置显示横线+竖线 this->setShowLineh(true); this->setShowLinev(true); this->setLineWidth(1); this->setLineColor(qRgb(50, 50, 50)); //设置边距 this->setPadding(5); //设置数据点的大小 this->setPointSize(0); //设置文本颜色 this->setTextColor(Qt::white); //设置XY轴范围值 this->setRangeX(m_Property.m_RangeX.width(), m_Property.m_RangeX.height(), m_Property.m_nTickCountX); this->setRangeY(m_Property.m_RangeY.width(), m_Property.m_RangeY.height(), m_Property.m_nTickCountY); customPlot->xAxis->setLabel(strXName); customPlot->yAxis->setLabel(strYName); customPlot->legend->setVisible(true); customPlot->axisRect()->setBackground(QBrush(m_Property.m_clrBg));//背景黑色 customPlot->xAxis->grid()->setPen(QPen(QColor(130, 130, 130), 1, Qt::PenStyle::DashLine));//网格白色虚线 customPlot->yAxis->grid()->setPen(QPen(QColor(130, 130, 130), 1, Qt::PenStyle::DashLine));//网格白色虚线 customPlot->xAxis->grid()->setSubGridPen(QPen(QColor(90, 90, 90), 1, Qt::DotLine));//网格浅色点线 customPlot->yAxis->grid()->setSubGridPen(QPen(QColor(90, 90, 90), 1, Qt::DotLine));//网格浅色点线 customPlot->xAxis->grid()->setSubGridVisible(true);//显示x轴子网格线 customPlot->yAxis->grid()->setSubGridVisible(true);//显示要轴子网格线 customPlot->xAxis->grid()->setZeroLinePen(QPen(Qt::white));//x轴0线颜色白色 customPlot->yAxis->grid()->setZeroLinePen(QPen(Qt::white));//y轴0线颜色白色 customPlot->xAxis->setTicks(false);//x轴不显示文本 //重新刷新显示 this->replot(); } void VCustomPlot::addGraph(QString strName, QColor color, int nLinsWidth, bool bFull) { QCPGraph* graph = customPlot->addGraph(); graph->setName(strName); if (bFull) { CustomPlotHelper::setGraphBrush(graph, color, 2); } QPen pen; pen.setColor(color); pen.setWidth(nLinsWidth); graph->setPen(pen); customPlot->replot(); } void VCustomPlot::delGraph(QString strName) { int nPlot = -1; for (int i = 0; i < customPlot->graphCount(); i++) { if (customPlot->graph(i)->name() == strName) { nPlot = i; } } if (customPlot->graphCount() <= nPlot) { return; } // 删除曲线 customPlot->removeGraph(nPlot); } void VCustomPlot::addValve(QString strName, double fKey, double fValue) { int nPlot = -1; for (int i = 0; i < customPlot->graphCount(); i++) { if (customPlot->graph(i)->name() == strName) { nPlot = i; } } if ((nPlot == -1) || (customPlot->graphCount() <= nPlot)) { return; } customPlot->graph(nPlot)->addData(fKey, fValue); int size = customPlot->xAxis->ticker()->tickCount(); customPlot->xAxis->setRange(fKey, size, Qt::AlignRight); } void VCustomPlot::addValve(int nPlot, double fValue) { if ((customPlot->graphCount() <= nPlot)) { return; } int nKey = customPlot->graph(nPlot)->dataCount(); double fKey = (double)nKey; customPlot->graph(nPlot)->addData(fKey, fValue); int size = customPlot->yAxis->ticker()->tickCount(); customPlot->xAxis->setRange(fKey, size, Qt::AlignRight); //customPlot->graph(nPlot)->rescaleValueAxis(); } void VCustomPlot::setRangeX(double min, double max, int tickCount) { customPlot->xAxis->setRange(min, max); customPlot->xAxis->ticker()->setTickCount(tickCount); } void VCustomPlot::setRangeY(double min, double max, int tickCount, bool percentY) { customPlot->yAxis->setRange(min, max); customPlot->yAxis->ticker()->setTickCount(tickCount); //如果开启了百分比格式,则先自动计算总共显示多少个数字 this->percentY = percentY; if (percentY) { vstring lab; vdouble key; int step = (max - min) / tickCount; for (int i = min; i <= max; i = i + step) { key << i; lab << QString("%1%").arg(i); } setLabY(key, lab); } } void VCustomPlot::setLabX(const vdouble & key, const vstring & lab) { //将对应的key用文本替代表示 #ifdef qcustomplot_v1 customPlot->xAxis->setAutoTicks(false); customPlot->xAxis->setAutoTickLabels(false); customPlot->xAxis->setTickVector(key); customPlot->xAxis->setTickVectorLabels(lab); #else //设置标尺为文本标尺 QSharedPointer ticker(new QCPAxisTickerText); ticker->addTicks(key, lab); customPlot->xAxis->setTicker(ticker); #endif } void VCustomPlot::setLabY(const vdouble & key, const vstring & lab) { //将对应的key用文本替代表示 #ifdef qcustomplot_v1 customPlot->yAxis->setAutoTicks(false); customPlot->yAxis->setAutoTickLabels(false); customPlot->yAxis->setTickVector(key); customPlot->yAxis->setTickVectorLabels(lab); #else //设置标尺为文本标尺 QSharedPointer ticker(new QCPAxisTickerText); ticker->addTicks(key, lab); customPlot->yAxis->setTicker(ticker); #endif } void VCustomPlot::addDataLine(const LineData & data) { QCPGraph* graph = customPlot->addGraph(); initGraph(graph, data); } void VCustomPlot::setDataLine(const LineData & data) { int index = data.index; if (customPlot->graphCount() > index) { QCPGraph* graph = customPlot->graph(index); initGraph(graph, data); //是否自适应坐标轴 if (data.autoScale) { graph->rescaleAxes(); } else { customPlot->xAxis->setRange(-offsetX, data.key.count() + offsetX, Qt::AlignLeft); } } } void VCustomPlot::initGraph(QCPGraph * graph, const LineData & data) { //设置画布名称 graph->setName(data.name); //设置画布数据 graph->setData(data.key, data.value); //设置线条画笔 graph->setPen(QPen(data.lineColor, data.lineWidth)); //设置连接风格 graph->setLineStyle((QCPGraph::LineStyle)data.lineStyle); //设置数据风格 QCPScatterStyle scatterStyle; scatterStyle.setPen(QPen(data.dataColor, data.dataWidth)); scatterStyle.setBrush(data.lineColor); scatterStyle.setSize(data.lineWidth); scatterStyle.setShape((QCPScatterStyle::ScatterShape)data.scatterShape); graph->setScatterStyle(scatterStyle); //设置填充画布 CustomPlotHelper::setGraphBrush(graph, data.lineColor, data.fillColor); } void VCustomPlot::initPropertyEx(CONTROL_PROPERTY_EX * pPropertyEx) { this->setBgColor(m_Property.m_clrBg); //隐藏表格线 this->getPlot()->xAxis->grid()->setVisible(false); //this->getPlot()->yAxis->grid()->setVisible(false); //初始化跟随鼠标游标 this->initTracer(); //初始化指示器数据高亮及悬停提示等 this->initItem(); QString strYName = m_Property.m_strText; if (m_Property.m_strText.isEmpty()) { strYName = "曲线图表"; } this->initUI("", strYName); // 备用颜色集合(按分块顺序赋值) m_defaultColors << QColor(0, 176, 180) << QColor(255, 192, 0) << QColor(0, 113, 193) << QColor(72, 103, 149) << QColor(185, 87, 86) << QColor(0, 177, 125) << QColor(214, 77, 84) << QColor(71, 164, 233) << QColor(34, 163, 169) << QColor(40, 45, 48) << QColor(162, 121, 197) << QColor(72, 202, 245) << QColor(0, 150, 121) << QColor(111, 9, 176) << QColor(250, 170, 20); // 初始化扩展属性 if (pPropertyEx == nullptr) { // 初始化曲线的条目数 this->m_Property.m_nSliceCount = DEFAULT_CUSTOMPLOT_COUNT; // 初始化扩展属性 this->initPropertyEx(); } else { this->m_PropertyEx = *pPropertyEx; // 根据分块数量先设置一个默认显示的Value for (int i = 0; i < m_Property.m_nSliceCount; i++) { QString strValue = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[i].strValue; QColor color = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[i].color; int nLineWidth = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[i].nLineWidth; addGraph(strValue, color, nLineWidth); } } //// 2022-9-11 为刷新链接绑定默认值(系统的执行次数) //this->bindDefaultRefreshDataLink(); } /// /// 初始化扩展属性 /// void VCustomPlot::initPropertyEx() { // 扩展属性的总名称 m_PropertyEx.m_strTitle = CUSTOM_PLOT_PROPERTY_EX_NAME; // 用于触发刷新的数据链接 m_PropertyEx.m_refreshLink.title = CUSTOM_PLOT_PROPERTY_EX_REFRESHLINK_NAME; // 强制设置 m_PropertyEx.m_refreshLink.bForce = true; // 初始化每一个扩展属性组(Wave控件只有一个属性组) PROPERTY_EX_GROUP group; // 列信息属性 group.strTitle = CUSTOM_PLOT_PROPERTY_EX_GROUP_NAME; group.strRelationKey = CUSTOM_PLOT_COUNT_NAME; //初始化列信息每一个子分组 for (int i = 0; i < m_Property.m_nSliceCount; i++) { PROPERTY_EX_SUBGROUP subGroup; this->initSubGroup(subGroup, i, GROUP_INDEX_CUSTOM_PLOT); // 保存子分组 group.subGroups.push_back(subGroup); // 创建曲线 addGraph(subGroup.strValue, m_defaultColors[i]); } // 保存本子分组定义信息 m_PropertyEx.m_groups.push_back(group); } /// /// 初始化一个扩展属性组 /// /// void VCustomPlot::initSubGroup(PROPERTY_EX_SUBGROUP & subGroup, int nIndex, int nSubGroupID) { if (nSubGroupID == GROUP_INDEX_CUSTOM_PLOT) { QString idx = QString::number(nIndex + 1); // 子分组名称 subGroup.strTitle = CUSTOM_PLOT_PROPERTY_EX_SUBGROUP_NAME + idx; // 列名称 + 数值 subGroup.strValueName = CUSTOM_PLOT_PROPERTY_EX_VALUE_NAME + idx; subGroup.strValue = CUSTOM_PLOT_PROPERTY_EX_VALUE_NAME + idx; subGroup.strLineWidthName = CUSTOM_PLOT_PROPERTY_EX_LINEWIDTH_NAME + idx; subGroup.nLineWidth = CUSTOM_PLOT_DEFAULT_LINEWIDTH; // 分块颜色名称 + 数值 subGroup.strColorName = CUSTOM_PLOT_PROPERTY_EX_COLOR_NAME + idx; // 按顺序给一个默认值(可能会越界) if (nIndex < m_defaultColors.size()) { subGroup.color = m_defaultColors.at(nIndex); } else { subGroup.color = m_defaultColors.at(nIndex - m_defaultColors.size()); } // 数据链接名称 DataLink dataLink; dataLink.title = CUSTOM_PLOT_PROPERTY_EX_LINK_NAME + idx; dataLink.defaultValue = g_pGvlManager->getDefaultValueByName(DEFAULT_VALUE_NULLSTRING); subGroup.dataLinks.push_back(dataLink); } } /// /// 设置块数 /// /// void VCustomPlot::setCustomPlotCount(const int& count) { if (this->m_Property.m_nSliceCount != count) { this->m_Property.m_nSliceCount = count; this->update(); } } /// /// 获取当前块数 /// int VCustomPlot::getCustomPlotCount() { return this->m_Property.m_nSliceCount; } /// /// 设置分块文字 /// /// /// void VCustomPlot::updateCustomPlotTitle(const QString & newValue, const int nIndex) { // 更新分块文字 QString& strValue = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].strValue; if (strValue != newValue) { strValue = newValue; if (customPlot->graphCount() >= nIndex) { customPlot->graph(nIndex)->setName(strValue); this->replot(); } } qDebug() << "VCustomPlot::updateColTitle - update [" << m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].strValueName << "] to [" << newValue << "]"; } /// /// 设置分块颜色 /// /// /// void VCustomPlot::updateCustomPlotColor(QColor newValue, const int nIndex) { QColor& color = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].color; int& nLinsWidth = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].nLineWidth; if (color != newValue) { color = newValue; if (customPlot->graphCount() >= nIndex) { QPen pen; pen.setColor(color); pen.setWidth(nLinsWidth); customPlot->graph(nIndex)->setPen(pen); this->replot(); } } qDebug() << "VCustomPlot::updateCustomPlotColor - update [" << m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].strColorName << "] to [" << newValue << "]"; } /// /// 更新图层线宽 /// /// /// void VCustomPlot::updateLineWidth(const int lineWidth, const int nIndex) { QColor& color = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].color; int& nLinsWidth = m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].nLineWidth; if (nLinsWidth != lineWidth) { nLinsWidth = lineWidth; // TODO:刷新预览 if (customPlot->graphCount() >= nIndex) { QPen pen; pen.setColor(color); pen.setWidth(nLinsWidth); customPlot->graph(nIndex)->setPen(pen); this->replot(); } } qDebug() << "VCustomPlot::updateLineWidth - update [" << m_PropertyEx.m_groups[GROUP_INDEX_CUSTOM_PLOT].subGroups[nIndex].strLineWidthName << "] to [" << lineWidth << "]"; } /// /// 设置分块数值 /// /// /// void VCustomPlot::updateCustomPlotValue(const int& newValue, const int nIndex) { addValve(nIndex, newValue); qDebug() << "VCustomPlot::updateCustomPlotValue - update m_Values[" << nIndex << "] to [" << newValue << "]"; if (!this->isHidden()) { this->replot(QCustomPlot::rpQueuedReplot); } } /// /// 调整块属性数量(虚函数) /// /// void VCustomPlot::updateExPropertyCount(const int fixCount, const QString & strPropName) { // 获取属性的当前数量 int curCount = this->getExPropertyCountByName(strPropName); // 子分组编号 int curGroup = this->getGroupIDByName(strPropName); // 检查有效性 if (curGroup < 0) { qDebug() << "[Error] VCustomPlot::updateExPropertyCount - nGroupID in invalid: " << curGroup; return; } // 如果需要增加 if (fixCount > 0) { int nEnd = curCount + fixCount; for (int i = curCount; i < nEnd; i++) { PROPERTY_EX_SUBGROUP subItem; this->initSubGroup(subItem, i, curGroup); m_PropertyEx.m_groups[curGroup].subGroups.push_back(subItem); addGraph(subItem.strValue, m_defaultColors[i]); } } // 如果需要减少 else if (fixCount < 0) { for (int i = 0; i < qAbs(fixCount); i++) { // 去掉对应的数据结构信息 m_PropertyEx.m_groups[curGroup].subGroups.pop_back(); // 同时去掉预览数值 customPlot->removeGraph(customPlot->graphCount() - 1); // 刷新 this->replot(); } } } /// /// 修改扩展属性(虚函数) /// /// /// void VCustomPlot::changeExProperties(QString strValueTitle, const QVariant & newValue) { // 如果改变了分块标题 if (strValueTitle.contains(CUSTOM_PLOT_PROPERTY_EX_VALUE_NAME)) { // 获取修改属性的索引 int nIndex = strValueTitle.remove(CUSTOM_PLOT_PROPERTY_EX_VALUE_NAME).toInt() - 1; // 如果索引值有效,则对应更新 if (nIndex >= 0) { // 修改对应Pie的数据结构内容 this->updateCustomPlotTitle(newValue.toString(), nIndex); } } // 如果改变了分块颜色 else if (strValueTitle.contains(CUSTOM_PLOT_PROPERTY_EX_COLOR_NAME)) { // 获取修改属性的索引 int nIndex = strValueTitle.remove(CUSTOM_PLOT_PROPERTY_EX_COLOR_NAME).toInt() - 1; // 如果索引值有效,则对应更新 if (nIndex >= 0) { // 修改对应Pie的数据结构内容 this->updateCustomPlotColor(newValue.value(), nIndex); } } // 如果改变了线宽 else if (strValueTitle.contains(CUSTOM_PLOT_PROPERTY_EX_LINEWIDTH_NAME)) { // 获取修改属性的索引 int nIndex = strValueTitle.remove(CUSTOM_PLOT_PROPERTY_EX_LINEWIDTH_NAME).toInt() - 1; // 如果索引值有效,则对应更新 if (nIndex >= 0) { // 刷新线宽 this->updateLineWidth(newValue.toInt(), nIndex); } } // 如果改变了数据链接(此处应该不需要手工更新) else if (strValueTitle.contains(CUSTOM_PLOT_PROPERTY_EX_REFRESHLINK_NAME) || strValueTitle.contains(CUSTOM_PLOT_PROPERTY_EX_LINK_NAME) ) { } // Error:不应该执行到这里 else { qWarning() << "[Error]: VCustomPlot::changeExProperties - invalid strValueTitle: " << strValueTitle; } }