QCustomPlot
目录
- 基本概念:
- graph
- xAxis
- yAxis
- ticker(刻度)
- customplot
- decorator(装饰器)
- pen
- ScatterStyle
- 设置显示的优先级
- Interactions
- legend
- 和滚动条的交互
- graphDataContainer(图数据容器)
- 图中添加文字说明
配置与使用
配置比较简单,只需在官网下载相应的.h文件和.cpp文件,然后在需要使用的文件中包括头文件即可,链接如下:
https://www.qcustomplot.com/index.php/download
我下载了上图的那个链接,包含了源码、文档和示例。
随后,在Qt项目中添加QCustomPlot的.h文件和.cpp文件。在ui界面上新建一个widget,将其提升为QCustomplot,接下来就可以用这个提升后的widget画图了。
右键单击widget,我这里是提升过后的效果。
按照下图所示顺序进行类型提升。
基本概念:
假设Qt界面中一个QWidget界面已经被提升为QCustomPlot,定义如下:QCustomPlot *customplot;
上面整个图就是这个customplot,它是整个ui的一部分,用ui.customplot
调用。
graph
- 在同一个x-y坐标下(一个坐标对应一个QCustomplot窗口)可以画出多个graph,每个图可以用
ui.customplot->graph(0)
,ui.customplot->graph(1)
,ui.customplo->graph(2)
…表示,其编号和数组一样,从0开始。 - 对于graph的相关操作:
ui.customplot->addGraph();//添加一个graph
ui.customplot->graphCount();//统计当前的显示窗口中有多少个graph
ui.customplot->graph(0)->addData();//顾名思意
ui.customplot->graph(0)->setLineStyle();//可设置graph线条样式,是实线还是虚线,也可以通过pen设置
ui.customplot->graph(0)->setPen();//通过一个QPen类设置更加丰富的样式
ui.customplot->graph(0)->setName();//顾名思意
ui.customplot->graph(0)->setScatterStyle();//设置折线图点的样式
ui.customplot->removeGraph();
xAxis
ui.customplot对应的x轴。图的上方的轴对应的是xAxis2
,图的下方对应的是xAxis
。常用API如下:
ui.customplot->xAxis->setVisible(); //坐标轴是否可见
ui.customplot->xAxis->setTicks(); // 刻度是否设置,参数是一个QCPAxisTickerDateTime指针
ui.customplot->xAxis->setTickLabels(); // 轴标签是否设置
ui.customplot->xAxis->setRange();//设置坐标显示范围(注意不是数据的范围),因为customplot可以只显示部分数据,通过滚动条查看其它部分的数据。
ui.customplot->rescaleAxes();//自动调整坐标轴的比例,显示全部数据。这会使setRange()失效。
yAxis
与xAxis
相似,其右边的轴对应的是yAxis2
,左边的轴对应的是yAxis
。
ticker(刻度)
用来设置标轴上的刻度,使用方法如下代码所示:
QSharedPointer< QCPAxisTickerDateTime > dataTick(new QCPAxisTickerDateTime);
dataTick->setTickCount(5); // 设置刻度数量为5,可以根据需要自行调整
dataTick->setTickStepStrategy(QCPAxisTicker::tssMeetTickCount); // 设置刻度步长策略为满足刻度数量
ui.customplot->xAxis->setTicker(dataTick);
从上图中也可看出x轴上有五个数字刻度。
customplot
对于QCustomPlot *customplot;
,customplot就是一整个统计图(可以是其它类型的图)显示窗口,统计图内可以有多条统计折线(可以是其它类型的线),每个线是一个graph。常用方法如下:
ui.customplot->addGraph();//添加一个graph
ui.customplot->graphCount();//统计当前的显示窗口中有多少个graph
ui.customplot->removeGraph();
ui.customplot->plot();//画图,显示所有的graph
ui.customplot->replot();//重新画图,如果图中某些元素改变了的话,用这个方法进行更新。
decorator(装饰器)
设置用户和图交互的样式。当前还没咋用到,只用过一次。在QCP::iSelectPlottables
交互模式下,点击某个graph后,整个线条都会变色。但有时我不希望有这种效果,这时可以用以下代码取消:
QCPSelectionDecorator* decorator0 = ui.widget_dispalyCoordinate->graph(0)->selectionDecorator();
// 设置选中装饰的笔为图形的原始笔,取消选中时的颜色变化效果
decorator0->setPen(ui.customplot->graph(0)->pen());
pen
设置连线的样式。例如线条的颜色、宽度等。
QPen pen = QPen(QColor(128, 128, 128));
pen.setStyle(Qt::PenStyle::DotLine);//虚线
pen.setWidth(3);
ui.customplot->graph(0)->setPen(pen);
ScatterStyle
QCustomPlot常用来画折线图。这个用来设置点的样式。
ui.customplot->graph(0)->setScatterStyle(QCPScatterStyle::ssDisc);//参数是点样式的枚举类型
设置显示的优先级
当多个graph存在重叠时,可以设置显示优先级来确定哪些优先显示,哪些被覆盖。
//设置显示的优先级
ui.customplot->graph(0)->setLayer("overlay"); // 第一个图形在 "overlay" 层,优先显示
ui.customplot->graph(1)->setLayer("underlay"); // 第二个图形在 "underlay" 层
ui.customplot->addLayer("overlay", ui.customplot->layer("main"), QCustomPlot::limAbove);
ui.customplot->addLayer("underlay", ui.customplot->layer("main"), QCustomPlot::limBelow);
Interactions
QCustomPlot本身默认可以让用户和图进行一定的交互,例如通过滚轮进行放大,通过鼠标左键进行拖拽等,这里主要讨论如何进行自定义交互样式。
通过ui.customplot->setInteractions(QCP::iSelectPlottables | QCP::iMultiSelect | QCP::iRangeZoom);
可以设置交互样式。
QCP::iSelectPlottables
意味着可以选中customplot中的组件,如graphs,curves,bars等,前面也说过,选中后有变色效果。QCP::iMultiSelect
意味着可以对组件进行多选。QCP::iRangeZoom
意味着可以对通过鼠标滚轮进行缩放。
还有其它的样式,详情见文档。
通过ui.customplot->setSelectionRectMode(QCP::srmSelect);
可以设置选择时的样式,通过枚举类QCP::SelectionRectMode
可以设置四种选择样式,如下所示:
我在自己的项目中使用的是srmSelect
,拖动鼠标可以获取一个矩形选择框。
通过ui.customplot->graph(0)->setSelectable()
可以针对每个graph设置相应的选择效果,如下图所示:
legend
这个暂时没咋用到,后面更新
和滚动条的交互
有时候数据范围过大,可能需要添加滚动条来查看其它区域。假设这里只设置水平的滚动条horizontalScrollBar
,首先设置数据范围ui->horizontalScrollBar->setRange(int min, int max)
,这个函数是从QAbstractSlider
继承来的。这里的min
和max
是滚动条的最小值和最大值,滚动条的值指的是滚动条左端在整个range中的位置。如下图所示:
为了方便,这里可以将min
和max
设置为要显示的数据的最小值和最大值。
然后通过信号和槽机制来控制滚动条和ui.customplot
的响应。connect函数可以按照如下方式写:
connect(ui.horizontalScrollBar, SIGNAL(valueChanged(int)), this, SLOT(horzScrollBarChanged(int)));
滚动条滚动时,其左端位置发生变化,发出valueChanged
信号。valueChanged()
函数的参数是整型的value
(即滚动条的值),槽函数也用这个value
来确定ui.customplot
显示哪部分的数据。槽函数可以按照如下方式写:
void horzScrollBarChanged(int value)
{
if (qAbs(ui.customplot->xAxis->range().center()-value) > 0.01) // if user is dragging plot, we don't want to replot twice
{
ui->plot->xAxis->setRange(value ui.customplot->xAxis->range().size(), Qt::AlignCenter);
ui->plot->replot();
}
}
PS: if user is dragging plot, we don’t want to replot twice,代码中的这个注释来自官方文档,实际上我也没看懂。
到这里就完成了滚动条和customplot的关联。
graphDataContainer(图数据容器)
我用其进行数据的复制。代码如下所示:
QSharedPointer<QCPGraphDataContainer> modify_data = ui.customplot->graph(0)->data();
//深度复制
QSharedPointer<QCPGraphDataContainer> copiedData(new QCPGraphDataContainer);
for (auto it = ui.customplot->graph(0)->data()->constBegin(); it != ui.customplot->graph(0)->data()->constEnd(); ++it)
{
copiedData->add(*it); // 添加数据点到新的容器
}
ui.customplot->graph(1)->setData(copiedData);
图中添加文字说明
通过QCPItemText类在customplot中添加文本,并设置文本的属性。
QCPItemText* textLabel = new QCPItemText(ui.cutPlotWidget);
// 设置文本标注的位置
textLabel->position->setType(QCPItemPosition::ptPlotCoords);
textLabel->position->setCoords((xData[0] + xData[xData.size() - 1]) / 2, (y_min + y_max)); // 在图表坐标左上角位置添加文字
QString text = QString("Distance is %1").arg(pickedDistance);
textLabel->setText(text);
textLabel->setFont(QFont("Arial", 12)); // 设置字体
textLabel->setColor(Qt::black); // 设置文字颜色
// 可选:设置文本标注的边框和填充颜色
textLabel->setBrush(QBrush(Qt::yellow)); // 填充颜色
QCPItemPosition
枚举类用来指定项目定义的位置,总共有四种枚举项,相关注释可见下图:
挖坑:后面会再展示几个demo代码进行进一步的说明。