#include "Chart.h" int Chart::ChannelIndex = 0; Chart::Chart(QChart *chart, QWidget *parent) { chart->legend()->setAlignment(Qt::AlignRight); chart->legend()->setMarkerShape(QLegend::MarkerShapeDefault); chart->setTheme(QChart::ChartThemeQt); //chart->setPlotArea(this->geometry()); chart->setAnimationOptions(QChart::SeriesAnimations); QValueAxis *axisX = new QValueAxis(); axisX->setRange(0, 60); axisX->setTickCount(11); axisX->setLabelFormat("%.1f"); chart->addAxis(axisX, Qt::AlignBottom); QValueAxis *axisY = new QValueAxis(); axisY->setRange(-3, 3); axisY->setTickCount(7); axisY->setLabelFormat("%.2f"); chart->addAxis(axisY, Qt::AlignLeft); setParent(parent); setChart(chart); setScroll(true); //chart->setPos(0,0); //默认不使用,因为使用显卡加速图形会闪 setUseOpenGL(true); if(!updateTimer) { updateTimer = new QTimer(this); connect(updateTimer,SIGNAL(timeout()), this,SLOT(timeout())); updateTimer->start(200);//5hz刷新 } } Chart::Chart(QWidget *parent) { setParent(parent); chart()->legend()->setAlignment(Qt::AlignRight); chart()->legend()->setMarkerShape(QLegend::MarkerShapeDefault); chart()->setTheme(QChart::ChartThemeQt); //chart()->setPlotArea(this->geometry()); chart()->setAnimationOptions(QChart::SeriesAnimations); QValueAxis *axisX = new QValueAxis(); axisX->setRange(0, 60); axisX->setTickCount(11); axisX->setLabelFormat("%.1f"); chart()->addAxis(axisX, Qt::AlignBottom); QValueAxis *axisY = new QValueAxis(); axisY->setRange(-1, 1); axisY->setTickCount(7); axisY->setLabelFormat("%.2f"); chart()->addAxis(axisY, Qt::AlignLeft); //chart()->setPos(0,0); setScroll(true); //默认不使用,因为使用显卡加速图形会闪 setUseOpenGL(true); if(!updateTimer) { updateTimer = new QTimer(this); connect(updateTimer,SIGNAL(timeout()), this,SLOT(timeout())); updateTimer->start(200);//5hz刷新 } } Chart::~Chart() { if(updateTimer) { if(updateTimer->isActive()) { updateTimer->stop(); } delete updateTimer; } } void Chart::leaveEvent(QEvent *e) { isPress = false; setCursor(Qt::ArrowCursor); QChartView::leaveEvent(e); } void Chart::hideEvent(QHideEvent *e) { qDebug() << e; } void Chart::showEvent(QShowEvent *e) { qDebug() << e; } void Chart::mouseMoveEvent(QMouseEvent *e) { if(isoperation) { const QPoint curPos = e->pos(); if (isPress) { QPoint offset = curPos - lastPoint; lastPoint = curPos; chart()->scroll(-offset.x(), offset.y()); } } //QChartView::mouseMoveEvent(e); } void Chart::mouseReleaseEvent(QMouseEvent *e) { if(isoperation) { isPress = false; setCursor(Qt::ArrowCursor); } //QChartView::mouseReleaseEvent(e); } void Chart::mousePressEvent(QMouseEvent *e) { if(isoperation) { if (e->button() == Qt::RightButton) { lastPoint = e->pos(); isPress = true; setCursor(Qt::ClosedHandCursor); } } //QChartView::mousePressEvent(e); } void Chart::mouseDoubleClickEvent(QMouseEvent *e) { qDebug() << "Chart double clicked" << e; //双击生成一个标 //QChartView::mouseDoubleClickEvent(e); } void Chart::wheelEvent(QWheelEvent *e) { if(isoperation) { //以鼠标坐标为中心进行缩放 QPointF curVal = chart()->mapToValue(QPointF(e->pos())); //缩放比例 const double factor = 1.5; switch(e->modifiers()) { case Qt::ControlModifier://垂直缩放 { QValueAxis *axis = dynamic_cast(chart()->axisY()); const double Min = axis->min(); const double Max = axis->max(); const double Central = curVal.y(); double bottomOffset; double topOffset; if (e->delta() > 0) {//放大 bottomOffset = 1.0 / factor * (Central - Min); topOffset = 1.0 / factor * (Max - Central); } else {//缩小 bottomOffset = 1.0 * factor * (Central - Min); topOffset = 1.0 * factor * (Max - Central); } chart()->axisY()->setRange(Central - bottomOffset, Central + topOffset); }break; case Qt::ShiftModifier://水平缩放 { QValueAxis *axis = dynamic_cast(chart()->axisX()); const double Min = axis->min(); const double Max = axis->max(); const double Central = curVal.x(); double bottomOffset; double topOffset; if (e->delta() > 0) {//放大 bottomOffset = 1.0 / factor * (Central - Min); topOffset = 1.0 / factor * (Max - Central); } else {//缩小 bottomOffset = 1.0 * factor * (Central - Min); topOffset = 1.0 * factor * (Max - Central); } chart()->axisX()->setRange(Central - bottomOffset, Central + topOffset); }break; default://水平移动 { QValueAxis *axis = dynamic_cast(chart()->axisX()); qreal dwidth = chart()->plotArea().width()/(axis->tickCount()*2); if(e->delta() > 0) { chart()->scroll(-dwidth,0); } else if(e->delta() < 0) { chart()->scroll(dwidth,0); } } } } //QChartView::wheelEvent(e); } void Chart::resizeEvent(QResizeEvent *e) { chart()->setPos(0,0); chart()->setGeometry(this->geometry()); //chart()->setPlotArea(this->geometry()); } void Chart::timeout(void)//10Hz { timeseries += updateTimer->interval() * 0.001f; chartUpdate(); } void Chart::chartUpdate(void) { //读取新数据,如果没有,那就保持 //当到达最大时(0.95),开始滚动 if(isScroll() == true) { QValueAxis *axis = dynamic_cast(chart()->axisX()); const double Min = axis->min(); const double Max = axis->max(); if(timeseries > (Min + (Max - Min) * 0.95)) { float err = (timeseries - (Min + (Max - Min) * 0.95)); chart()->axisX()->setRange(Min + err,Max + err); } } if(isoperation == false) { QValueAxis *axis = dynamic_cast(chart()->axisX()); const double Min = axis->min(); const double Max = axis->max(); MaxCount = 0.86 * (Max - Min)/(updateTimer->interval() * 0.001); //自适应纵轴 QList yMax; QList yMin; QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { QLineSeries *s = qobject_cast(serie); if(s) { QVector pv = s->pointsVector(); //qDebug() << s->name() << pv; float max = pv.at(0).y(); float min = pv.at(0).y(); foreach (QPointF p, pv) { if(max < p.y()) { max = p.y(); } if(min > p.y()) { min = p.y(); } } yMax.append(max); yMin.append(min); } } if((yMax.size() > 0)&&(yMin.size() > 0)) { float maxValue = yMax.at(0); foreach (float max, yMax) { if(maxValue < max) { maxValue = max; } } float minValue = yMin.at(0); foreach (float min, yMin) { if(minValue > min) { minValue = min; } } float scale = 0.5; if(maxValue != minValue) { scale = qAbs((maxValue - minValue) * 0.5 * 0.2); if(scale == 0) { scale = 0.5; } } float top = maxValue + scale; float bottom = minValue - scale; if(top == bottom) { top += 1; bottom -= 1; } chart()->axisY()->setRange(bottom,top); //chart()->axisY()->setRange((int)(minValue - qAbs(minValue - 1) * 0.5 - 1) ,(int)(maxValue + qAbs(maxValue + 1) * 0.5 + 1)); update(); } } } void Chart::setUseOpenGL(const bool &value) { isOpenGL= value; } bool Chart::addSeries(QString name = tr("new")) { //查找有没有这个名字的序列 bool isContain = false; QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { if(serie->name() == name) { isContain = true; } } if(isContain == false) { QLineSeries *s = new QLineSeries(); s->setColor(ColorMap::Color[ChannelIndex]); s->setName(name); s->setPointLabelsClipping(true); s->pen().setStyle(Qt::SolidLine); //s->append(timeseries,0); s->setUseOpenGL(isOpenGL); chart()->addSeries(s); chart()->setAxisX(chart()->axisX(),s); chart()->setAxisY(chart()->axisY(),s); ChannelIndex ++; if(ChannelIndex >= 16) { ChannelIndex = 0; } } else { qInfo() << "this chart has contain a serie name by :" << name; } return isContain; } bool Chart::addSeries(QString name = tr("new"), int index = 0) { if(index >= 16) { int a = index/16; ChannelIndex = index - a*16; } //查找有没有这个名字的序列 bool isContain = false; QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { if(serie->name() == name) { isContain = true; } } if(isContain == false) { QLineSeries *s = new QLineSeries(); s->setColor(ColorMap::Color[ChannelIndex]); s->setName(name); s->setPointLabelsClipping(true); s->pen().setStyle(Qt::SolidLine); //s->append(timeseries,0); s->setUseOpenGL(isOpenGL); chart()->addSeries(s); chart()->setAxisX(chart()->axisX(),s); chart()->setAxisY(chart()->axisY(),s); ChannelIndex ++; if(ChannelIndex >= 16) { ChannelIndex = 0; } } else { qInfo() << "this chart has contain a serie name by :" << name; } return isContain; } bool Chart::addSeries(QString name = tr("new"),QColor color = QColor("#FFFFFF"),Qt::PenStyle pen = Qt::PenStyle(Qt::SolidLine)) { //查找有没有这个名字的序列 bool isContain = false; QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { if(serie->name() == name) { isContain = true; } } if(isContain == false) { QLineSeries *s = new QLineSeries(); s->setColor(color); s->setName(name); s->setPointLabelsClipping(true); s->pen().setStyle(pen); //s->append(timeseries,0); s->setUseOpenGL(isOpenGL); chart()->addSeries(s); chart()->setAxisX(chart()->axisX(),s); chart()->setAxisY(chart()->axisY(),s); ChannelIndex ++; if(ChannelIndex >= 16) { ChannelIndex = 0; } } else { qInfo() << "this chart has contain a serie name by :" << name; } return isContain; } void Chart::setSerieData(QString name,QVariant data) { //timeseries++; //qDebug() << timeseries << timeseries; //出新了比以前更大或者更小的值,那么就设置一下量程 { QValueAxis *axis = dynamic_cast(chart()->axisY()); if(data.toDouble() > axis->max()) { //设置最大值 const double Min = axis->min(); double FreeArea = (data.toDouble() - Min) * 0.1; chart()->axisY()->setRange(Min, data.toDouble() + FreeArea); } else if(data.toDouble() < axis->min()) { //设置最小值 const double Max = axis->max(); double FreeArea = (Max - data.toDouble()) * 0.1; chart()->axisY()->setRange(data.toDouble() - FreeArea, Max); } } //查找有没有这个名字的序列 bool isContain = false; QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { QLineSeries *s = qobject_cast(serie); if(s->name() == name) { s->append(timeseries,data.toDouble()); if(isOperation() == false) { if(s->pointsVector().size() > MaxCount) { QList pv = s->points(); pv.removeFirst(); s->clear(); s->replace(pv); //qDebug() << "remove()" << s->points().size() ; } } isContain = true; } } if(isContain == false) { addSeries(name,ChannelIndex); ChannelIndex ++; if(ChannelIndex >= 16) { ChannelIndex = 0; } QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { QLineSeries *s = qobject_cast(serie); if(s->name() == name) { s->append(timeseries,data.toDouble()); } } } chartUpdate(); } void Chart::removeSerie(QString name) { //找到,删除 QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { QLineSeries *s = qobject_cast(serie); if(s) { QString str = s->name(); if(str.contains('[')) { str = str.left(str.indexOf('[')); } if(str == name) { chart()->removeSeries(s); s->clear(); s->deleteLater(); delete s; } } } update(); } void Chart::removeAllSerie(void) { //找到,删除 QList slist = chart()->series(); for(QAbstractSeries *serie:slist) { QLineSeries *s = qobject_cast(serie); if(s) { chart()->removeSeries(s); s->clear(); s->deleteLater(); delete s; } } update(); }