Files
gcs-nf/App/ComponentUI/Scope/Chart.cpp
T
2022-03-28 16:25:00 +08:00

712 lines
17 KiB
C++

#include "Chart.h"
int Chart::ChannelIndex = 0;
Chart::Chart(QChart *chart, QWidget *parent)
{
QFile file(":/qss/Scope.qss");
file.open(QFile::ReadOnly);
QTextStream filetext(&file);
QString stylesheet = filetext.readAll();
this->setStyleSheet(stylesheet);
file.close();
chart->legend()->setAlignment(Qt::AlignRight);
chart->legend()->setMarkerShape(QLegend::MarkerShapeDefault);
chart->setTheme(QChart::ChartThemeQt);
chart->setBackgroundBrush(Qt::white);
//chart->setPlotArea(this->geometry());
chart->setAnimationOptions(QChart::SeriesAnimations);
QFont font;
font.setFamily("微软雅黑");
font.setPointSize(9);
QValueAxis *axisX = new QValueAxis();
axisX->setLabelsFont(font);
axisX->setRange(0, 60);
axisX->setTickCount(11);
axisX->setLabelFormat("%.0f");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis();
axisY->setLabelsFont(font);
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);
chart->resize(parent->size());
//默认不使用,因为使用显卡加速图形会闪
setUseOpenGL(true);
chart->layout()->setContentsMargins(2, 2, 2, 2);
//chart->setContentsMargins(0, 0, 0, 0); //设置外边界全部为0
chart->setMargins(QMargins(0, 0, 0, 0));//设置内边界全部为0
chart->setBackgroundRoundness(0); //设置背景区域无圆角
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()->setBackgroundBrush(Qt::white);
//chart()->setPlotArea(this->geometry());
chart()->setAnimationOptions(QChart::SeriesAnimations);
QFont font;
font.setFamily("微软雅黑");
font.setPointSize(9);
QValueAxis *axisX = new QValueAxis();
axisX->setLabelsFont(font);
axisX->setRange(0, 60);
axisX->setTickCount(11);
axisX->setLabelFormat("%.0f");
chart()->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis();
axisY->setLabelsFont(font);
axisY->setRange(-1, 1);
axisY->setTickCount(7);
axisY->setLabelFormat("%.2f");
chart()->addAxis(axisY, Qt::AlignLeft);
chart()->setPos(0,0);
chart()->resize(parent->size());
setScroll(true);
//默认不使用,因为使用显卡加速图形会闪
setUseOpenGL(true);
chart()->layout()->setContentsMargins(2, 2, 2, 2);
//chart()->setContentsMargins(0, 0, 0, 0); //设置外边界全部为0
chart()->setMargins(QMargins(0, 0, 0, 0));//设置内边界全部为0
chart()->setBackgroundRoundness(0); //设置背景区域无圆角
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::enterEvent(QEvent *event)
{
//setCursor(Qt::SizeVerCursor);
QChartView::leaveEvent(event);
}
void Chart::leaveEvent(QEvent *event)
{
isPress = false;
setCursor(Qt::ArrowCursor);
QChartView::leaveEvent(event);
}
void Chart::hideEvent(QHideEvent *event)
{
qDebug() << event;
}
void Chart::showEvent(QShowEvent *event)
{
qDebug() << event;
}
void Chart::mouseMoveEvent(QMouseEvent *event)
{
if(isoperation)
{
const QPoint curPos = event->pos();
if (isPress)
{
QPoint offset = curPos - lastPoint;
lastPoint = curPos;
chart()->scroll(-offset.x(), offset.y());
}
}
//QChartView::mouseMoveEvent(e);
}
void Chart::mouseReleaseEvent(QMouseEvent *event)
{
if(isoperation)
{
isPress = false;
setCursor(Qt::ArrowCursor);
}
//QChartView::mouseReleaseEvent(e);
}
void Chart::mousePressEvent(QMouseEvent *event)
{
if(isoperation)
{
if (event->button() == Qt::RightButton)
{
lastPoint = event->pos();
isPress = true;
setCursor(Qt::ClosedHandCursor);
}
}
//QChartView::mousePressEvent(e);
if(Select())
{
setSelect(false);
}
else
{
setSelect(true);
}
emit select(Select());//被选中
}
void Chart::mouseDoubleClickEvent(QMouseEvent *event)
{
qDebug() << "Chart double clicked" << event;
//双击生成一个标
//QChartView::mouseDoubleClickEvent(e);
}
void Chart::wheelEvent(QWheelEvent *event)
{
if(isoperation)
{
//以鼠标坐标为中心进行缩放
QPointF curVal = chart()->mapToValue(QPointF(event->pos()));
//缩放比例
const double factor = 1.5;
switch(event->modifiers())
{
case Qt::ControlModifier://垂直缩放
{
QValueAxis *axis = dynamic_cast<QValueAxis*>(chart()->axisY());
const double Min = axis->min();
const double Max = axis->max();
const double Central = curVal.y();
double bottomOffset;
double topOffset;
if (event->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://水平缩放
{
//setCursor(Qt::SizeVerCursor);
QValueAxis *axis = dynamic_cast<QValueAxis*>(chart()->axisX());
const double Min = axis->min();
const double Max = axis->max();
const double Central = curVal.x();
double bottomOffset;
double topOffset;
if (event->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<QValueAxis*>(chart()->axisX());
qreal dwidth = chart()->plotArea().width()/(axis->tickCount()*2);
if(event->delta() > 0)
{
chart()->scroll(-dwidth,0);
}
else if(event->delta() < 0)
{
chart()->scroll(dwidth,0);
}
}
}
}
//QChartView::wheelEvent(e);
}
void Chart::resizeEvent(QResizeEvent *event)
{
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<QValueAxis*>(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<QValueAxis*>(chart()->axisX());
const double Min = axis->min();
const double Max = axis->max();
MaxCount = 0.86 * (Max - Min)/(updateTimer->interval() * 0.001);
//自适应纵轴
QList<float> yMax;
QList<float> yMin;
QList<QAbstractSeries *> slist = chart()->series();
for(QAbstractSeries *serie:slist)
{
QLineSeries *s = qobject_cast<QLineSeries *>(serie);
if(s)
{
QVector<QPointF> 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<QAbstractSeries *> 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->pen().setColor(ColorMap::Color[ChannelIndex]);
//s->append(timeseries,0);
s->setUseOpenGL(isOpenGL);
chart()->addSeries(s);
chart()->setAxisX(chart()->axisX(),s);
chart()->setAxisY(chart()->axisY(),s);
ChannelIndex ++;
if(ChannelIndex >= ColorMap::size())
{
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)
{
//查找有没有这个名字的序列
bool isContain = false;
QList<QAbstractSeries *> 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->pen().setColor(ColorMap::Color[ChannelIndex]);
//s->append(timeseries,0);
s->setUseOpenGL(isOpenGL);
chart()->addSeries(s);
chart()->setAxisX(chart()->axisX(),s);
chart()->setAxisY(chart()->axisY(),s);
qDebug() << ChannelIndex << s->color().name() << ColorMap::Color[ChannelIndex].name();
connect(s,&QLineSeries::clicked,
this,&Chart::lineClicked);
ChannelIndex ++;
if(ChannelIndex >= ColorMap::size())
{
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<QAbstractSeries *> 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->pen().setColor(ColorMap::Color[ChannelIndex]);
//s->append(timeseries,0);
s->setUseOpenGL(isOpenGL);
chart()->addSeries(s);
chart()->setAxisX(chart()->axisX(),s);
chart()->setAxisY(chart()->axisY(),s);
ChannelIndex ++;
if(ChannelIndex >= ColorMap::size())
{
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<QValueAxis*>(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<QAbstractSeries *> slist = chart()->series();
for(QAbstractSeries *serie:slist)
{
QLineSeries *s = qobject_cast<QLineSeries *>(serie);
if(s->name() == name)
{
s->append(timeseries,data.toDouble());
if(isOperation() == false)
{
if(s->pointsVector().size() > MaxCount)
{
QList<QPointF> pv = s->points();
pv.removeFirst();
s->clear();
s->replace(pv);
//qDebug() << "remove()" << s->points().size() ;
}
}
isContain = true;
}
}
if(isContain == false)
{
addSeries(name,ChannelIndex);
QList<QAbstractSeries *> slist = chart()->series();
for(QAbstractSeries *serie:slist)
{
QLineSeries *s = qobject_cast<QLineSeries *>(serie);
if(s->name() == name)
{
s->append(timeseries,data.toDouble());
}
}
}
chartUpdate();
}
void Chart::removeSerie(QString name)
{
//找到,删除
QList<QAbstractSeries *> slist = chart()->series();
for(QAbstractSeries *serie:slist)
{
QLineSeries *s = qobject_cast<QLineSeries *>(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<QAbstractSeries *> slist = chart()->series();
for(QAbstractSeries *serie:slist)
{
QLineSeries *s = qobject_cast<QLineSeries *>(serie);
if(s)
{
chart()->removeSeries(s);
s->clear();
s->deleteLater();
delete s;
}
}
update();
}
void Chart::lineClicked(const QPointF &point)
{
qDebug() << "clicked";
QObject *obj = sender();
QLineSeries *s = qobject_cast<QLineSeries *>(obj);
if(s)
{
s->pen().setWidth(10);
}
}
void Chart::lineHover(const QPointF &point, bool state)
{
QObject *obj = sender();
QLineSeries *s = qobject_cast<QLineSeries *>(obj);
if(s)
{
s->pen().setWidth(10);
qDebug() << "hover";
}
}