备注:
1、动态增加/移除坐标系;
2、多段y轴,共用同一个x轴;
3、x轴y轴数据同步,当放大缩小表格时;
4、通过定时器0.5s更新一次数据;
****亲,感觉不错的话点个赞哦****
一、项目中结合树形目录勾选框,进行动态增加和删除勾选框,通过定时器模拟数据进行显示
connect(m_treeWidget, &TreeDirectoryWidget::sig_itemCheckChange, this, &WdtCustomChart::SlotItemChange);
connect(m_data_timer, SIGNAL(timeout()), this, SLOT(SlotDataTimeOut()));
void WdtCustomChart::SlotItemChange(QString id, bool check)
{
//根据树形目录勾选框是否勾选进行动态增加/移除坐标系
if (check)
{
auto rows = m_plot->plotLayout()->rowCount();
QCPAxisRect* axisRect = CreateQCPAxisRect(id);
m_plot->plotLayout()->addElement(rows++, 0, axisRect);
UpdateSettingCommonXaXisx();
ConnectAllAxisx(true);
}
else
{
//移除该通道坐标及曲线
RemoveQCPAxisRect(id);
}
m_plot->replot();
}
void WdtCustomChart::SlotDataTimeOut()
{
static double key = 0;; // 开始到现在的时间,单位
for (auto& pair : m_channel_plots.toStdMap())
{
int value = qrand() % 20;
auto channel = pair.first;
auto graph = pair.second;
graph->addData(key,value);
if (m_channel_axises.contains(channel))
{
auto AxisRec = m_channel_axises.value(channel);
//QCPAxis* poAxisY = AxisRec->axis(QCPAxis::atLeft); //y轴
//int upper = (int)(poAxisY->range().upper);
//if (upper < value)
// poAxisY->setRangeUpper(value + 10);
if (key > 20)
AxisRec->axis(QCPAxis::atBottom)->setRange(key, 20, Qt::AlignRight);
}
}
key+=0.5;
//绘图
m_plot->replot();
}
static const QColor colors[] =
{
Qt::red,
Qt::green,
Qt::blue,
Qt::cyan,
Qt::magenta,
Qt::gray,
Qt::darkRed,
Qt::darkGreen,
Qt::darkBlue,
Qt::darkCyan,
};
二、核心代码:
1、动态增加channel所对应的坐标系
QCPAxisRect* WdtCustomChart::CreateQCPAxisRect(QString channel)
{
//channel代表坐标系id
QCPAxisRect* axisRect = new QCPAxisRect(m_plot, true);
axisRect->setupFullAxesBox(true);
axisRect->setRangeZoom(Qt::Horizontal | Qt::Vertical);
QCPAxis* poAxisX = axisRect->axis(QCPAxis::atBottom); //x轴
QCPAxis* poAxisY = axisRect->axis(QCPAxis::atLeft); //y轴
poAxisX->setRange(0, 20);
poAxisY->setRange(0, 50);
axisRect->axis(QCPAxis::atTop)->setVisible(false);
axisRect->axis(QCPAxis::atRight)->setVisible(false);
poAxisX->grid()->setSubGridVisible(true);
poAxisY->grid()->setSubGridVisible(true);
axisRect->setAutoMargins(QCP::msRight | QCP::msLeft);
axisRect->setMargins(QMargins(100, 0, 0, 0));
poAxisY->setPadding(5); // 这里的5是你想要的额外填充
poAxisY->setTickLabelPadding(10); // 这里的5是你想要的额外填充
poAxisY->setLabelPadding(10); // 这里的5是你想要的额外填充
poAxisX->setVisible(true);
poAxisX->setLabel(Trans("时间(s)"));
//设置x轴y轴自由缩放
QList<QCPAxis*> aaxisField;
aaxisField << poAxisX;
aaxisField << poAxisY;
axisRect->setRangeZoomAxes(aaxisField);
poAxisY->setVisible(true);
poAxisY->setLabel(Trans("通道") + channel);
auto poGraph = m_plot->addGraph(poAxisX, poAxisY);
QPen pen;
pen.setColor(colors[qrand() % 10]);
poGraph->setPen(pen);
//下面这两行使得Y轴轴线总是对齐
axisRect->setAutoMargins(QCP::MarginSide::msLeft | QCP::MarginSide::msRight);
m_channel_axises.insert(channel.toInt(), axisRect);
m_channel_plots.insert(channel.toInt(), poGraph);
return axisRect;
}
2、动态删除channel所对应的坐标系
void WdtCustomChart::RemoveQCPAxisRect(QString channel)
{
if (m_channel_axises.contains(channel.toInt()) && m_channel_plots.contains(channel.toInt()))
{
auto axes_rect = m_channel_axises.value(channel.toInt());
auto graph_plot = m_channel_plots.value(channel.toInt());
m_plot->plotLayout()->remove(axes_rect);
m_plot->plotLayout()->simplify();
m_channel_axises.remove(channel.toInt());
m_channel_plots.remove(channel.toInt());
}
}
3、//多段y轴共用同一个x轴
void WdtCustomChart::UpdateSettingCommonXaXisx()
{
auto elements = m_plot->plotLayout()->elementCount();
for (int row = 0; row < elements; row++)
{
QCPAxisRect* poRecti = (QCPAxisRect*)m_plot->plotLayout()->element(row, 0);
if (poRecti)
{
//布局中最后一个元素进行设置
if (row == (elements - 1))
{
poRecti->setMargins(QMargins(100, 0, 0, 40));
poRecti->axis(QCPAxis::atBottom)->setVisible(true);
}
else
{
poRecti->setMargins(QMargins(100, 0, 0, 0));
poRecti->axis(QCPAxis::atBottom)->setVisible(false);
}
}
}
}
4、//当鼠标放大缩小上下移动时 ,多段y轴x轴同步
void WdtCustomChart::ConnectAllAxisx(bool on)
{
auto elements = m_plot->plotLayout()->elementCount();
for (int i = 0; i < elements; i++)
{
QCPAxisRect* poRecti = (QCPAxisRect*)m_plot->plotLayout()->element(i, 0);
for (int j = 0; j < elements; j++)
{
QCPAxisRect* poRectj = (QCPAxisRect*)m_plot->plotLayout()->element(j, 0);
if (poRectj && poRecti && i!=j)
{
connect(poRecti->axis(QCPAxis::atBottom), QOverload<const QCPRange&>::of(&QCPAxis::rangeChanged),
poRectj->axis(QCPAxis::atBottom), QOverload<const QCPRange&>::of(&QCPAxis::setRange));
connect(poRecti->axis(QCPAxis::atLeft), QOverload<const QCPRange&>::of(&QCPAxis::rangeChanged),
poRectj->axis(QCPAxis::atLeft), QOverload<const QCPRange&>::of(&QCPAxis::setRange));
}
}
}
}
5、初始化QCustomPlot
void WdtCustomChart::initPlot()
{
m_plot = new QCustomPlot(this);
m_plot->plotLayout()->clear();
允许用户用鼠标拖动轴范围,以鼠标为中心滚轮缩放,点击选择图形:
m_plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
}
标签:plot,poAxisY,Qt,axisRect,QCustomPlot,移除,多段,QCPAxis,channel
From: https://blog.csdn.net/weixin_45074487/article/details/137076400