Qt做曲线图绘制有很多类,如QChart,QCustomPlot和QWT。我之前一直用QChart,但是感觉它在数据量大的时候会有点卡顿,甚至有时候会直接让程序崩溃。所以推荐还是一步到位,直接用其他两种吧!
1.美观——背景,线条颜色,线条宽度,字体,边框间距,坐标轴间隔;
2.以鼠标为中心进行缩放,以及重置曲线图;
3.显示鼠标点所在坐标值;
4.图中曲线的名称图例;
5.支持拖拽;
6.支持添加预警线;
7.支持多通道数据显示;
8.支持数据统计功能;——最大值,最小值,平均值,方差。
9.支持自定义曲线的显示;——图例及图例框位置、效果、字体、颜色、X轴标签文字、背景颜色、背景标签线大小
10.支持框选折线图,筛选表中数据的功能;
下图左是不加如下的代码,下图右是加了如下的代码效果。
chart->setContentsMargins(0, 0, 0, 0); //设置外边界全部为0
chart->setMargins(QMargins(0, 0, 0, 0));//设置内边界全部为0
下图左是不加如下的代码,下图右是加了如下的代码效果。
chart->layout()->setContentsMargins(0, 0, 0, 0);//设置边界为0
使用QCustomPlot需要先下载这个类,然后将.h和.cpp文件添加,最后将widget提升为QCustomPlot类。
如下的代码包括:添加一个图例,添加图例的数据,设置坐标轴的显示范围。
//定义两个可变数组存放绘图的坐标数据
QVector<double> x(101),y(101);//分别存放x和y坐标的数据,101为数据长度
//添加数据,我们这里演示y=x^3,为了正负对称,我们x从-50到+50
for(int i=0;i<101;i++)
{
x[i] = i-50;
y[i] = x[i] * x[i] * x[i];
}
ui->widget->addGraph();//添加一条数据
ui->widget->graph(0)->setData(x,y);//注意这里必须为QVector且是double类型的变量
//设置坐标轴显示范围,否则我们只能看到默认的范围
ui->widget->xAxis->setRange(-60,60);
ui->widget->yAxis->setRange(-60*60*60-100,60*60*60+100);
运行效果图如下:
下面代码的0代表第一个图例,如果有多个图例可以是1,2,3等等。新建图例是上面的addgraph()函数。
//设置图例名称
ui->widget->graph(0)->setName("line");
ui->widget->legend->setVisible(true);
效果图如下:
各类图类的总结链接:https://blog.csdn.net/u014252478/article/details/80430000
详细的图层相关知识及背景设置见链接:https://blog.csdn.net/u014252478/article/details/79928433
图的外观设置见链接:https://segmentfault.com/a/1190000021931918
大佬的学习博客见链接:https://www.cnblogs.com/swarmbees/p/6060473.html
线条样式的设置见链接:https://blog.csdn.net/yxy244/article/details/100033549
坐标轴设置的详细博客见链接:https://blog.csdn.net/yxy244/article/details/100311112
第一,背景的设置
由于图层有多层,每层都有背景,下面的代码是设置我们通常理解的坐标轴背景颜色。
//设置背景颜色
QLinearGradient plotGradient;
plotGradient.setStart(0, 0);
plotGradient.setFinalStop(0, 350);
plotGradient.setColorAt(0, QColor(80, 80, 80));
plotGradient.setColorAt(1, QColor(50, 50, 50));
//ui->widget->setBackground(plotGradient);
ui->widget->axisRect()->setBackground(plotGradient); // 设置QCPAxisRect背景颜色
效果图如下:
第二,设置线条颜色,宽度以及图刷
//设置线条颜色
QPen pen;
pen.setWidth(3);//线宽
pen.setColor(Qt::red);//颜色
ui->widget->graph(0)->setPen(pen);
//设置画刷:与0刻度线围成区域
ui->widget->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 100)));//后面的100是不透明度
效果图如下:
第三,设置坐标轴刻度线的风格
//设置坐标轴刻度线
ui->widget->xAxis->setBasePen(QPen(Qt::white, 1)); // 轴线的画笔
ui->widget->xAxis->setTickPen(QPen(Qt::white, 1)); // 轴刻度线的画笔
ui->widget->xAxis->setSubTickPen(QPen(Qt::white, 1)); // 轴子刻度线的画笔
ui->widget->xAxis->setTickLabelColor(Qt::white); // 轴刻度文字颜色
ui->widget->xAxis->setLabel("x轴"); // 只有设置了标签,轴标签的颜色才会显示
ui->widget->xAxis->setLabelColor(Qt::white); // 轴标签颜色
ui->widget->xAxis->setTickLengthIn(3); // 轴线内刻度的长度
ui->widget->xAxis->setTickLengthOut(5); // 轴线外刻度的长度
ui->widget->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow); // 设置轴线结束时的风格为 实角三角形但内部有凹陷的形状, setLowerEnding设置轴线开始时的风格
ui->widget->yAxis->setBasePen(QPen(Qt::white, 1)); // 轴线的画笔
ui->widget->yAxis->setTickPen(QPen(Qt::white, 1)); // 轴刻度线的画笔
ui->widget->yAxis->setSubTickPen(QPen(Qt::white, 1)); // 轴子刻度线的画笔
ui->widget->yAxis->setTickLabelColor(Qt::white); // 轴刻度文字颜色
ui->widget->yAxis->setLabel("y轴"); // 只有设置了标签,轴标签的颜色才会显示
ui->widget->yAxis->setLabelColor(Qt::white); // 轴标签颜色
ui->widget->yAxis->setTickLengthIn(3); // 轴线内刻度的长度
ui->widget->yAxis->setTickLengthOut(5); // 轴线外刻度的长度
ui->widget->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow); // 设置轴线结束时的风格为 实角三角形但内部有凹陷的形状, setLowerEnding设置轴线开始时的风格
效果图如下:
第四,字体设置
看不出变化,这个也不太重要吧。
//设置字体
ui->widget->setFont(QFont(font().family(), 9));//设置文本的字体
//setLabelFont: 设置label字体
//setTickLabelFont:设置刻度label字体
第五,坐标轴间隔
//坐标轴间隔
ui->widget->xAxis->setAutoTickStep(false); //先关闭自动间隔
ui->widget->yAxis->setAutoTickStep(false); //先关闭自动间隔
ui->widget->xAxis->setTickStep(30);
ui->widget->yAxis->setTickStep(50000);
效果图如下:
//设置曲线可拖拽 滚轮放大缩小 图像可选择
ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
这里的坐标值,是以坐标轴为基准的。且坐标信息是附在鼠标处显示的。
//第一,包含鼠标事件头文件
#include <QMouseEvent>
//第二,构建鼠标事件与响应槽函数的连接
/**** 鼠标点数据显示 ****/
connect(ui->widget,&QCustomPlot::mouseMove,this,&MainWindow::myMoveEvent);
//第三,鼠标响应事件
void MainWindow::myMoveEvent(QMouseEvent *event)
{
double x = event->pos().x();
double y = event->pos().y();
double x_ = ui->widget->xAxis->pixelToCoord(x);
double y_ = ui->widget->yAxis->pixelToCoord(y);
QString str = QString("x:%1;\ny:%2").arg(QString::number(x_,10,3))
.arg(QString::number(y_,10,3));
QToolTip::showText(cursor().pos(),str,ui->widget);
}
效果图如下:
大佬博客的参考链接:https://blog.csdn.net/yxy244/article/details/100547688
步骤:第一,设置曲线图可框选;第二,定义框选信号的槽函数。
下面的代码是槽函数。void MainWindow::on_widget_selectionChangedByUser()是响应曲线图框选动作的。
注意:on_widget_selectionChangedByUser()函数隐含着把selectionChangedByUser()信号和这个函数(作为槽函数)连接起来了。 未来移植的时候,需要改的就是widget这个名字。比如你的UI里,如下图,绘图用控件的名称是Curve就改成on_Curve_selectionChangedByUser()
对于信号与槽机制,搜索一下QMetaObject::connectSlotsByName就会有答案了。隐含的信号与槽函数定义方式。
//选择的数据变化
void MainWindow::on_widget_selectionChangedByUser()
{
QCustomPlot* customPlot=ui->widget;
qDebug()<<"ok111";
//清空listwidget
//ui->lst_data->clear();
for(int i=0;i<customPlot->graphCount();i++)
{
qDebug()<<"ok1";
//遍历有被选中的graph
if(customPlot->graph(i)->selected())
{
qDebug()<<"ok2";
QCPDataSelection selection =customPlot->graph(i)->selection();
//遍历选中范围
for(int j=0;j<selection.dataRangeCount();j++)
{
qDebug()<<"ok3";
QCPDataRange dataRange = selection.dataRange(j);
//遍历数据
for(int k=dataRange.begin();k<dataRange.end();k++)
{
qDebug()<<"ok4";
QString str_key = QString::number(customPlot->graph(i)->data()->at(k)->key);
QString str_value = QString::number(customPlot->graph(i)->data()->at(k)->value);
QString str_at= QString::number(i);
//添加到listwidget
qDebug()<<"曲线"<<str_at<<":"<<str_key<<", "<<str_value;
//ui->lst_data->addItem("曲线"+str_at+":"+str_key+", "+str_value);
}
}
}
}
//滚动到底部
//ui->lst_data->scrollToBottom();
// ui->lst_data->scrollToTop();
}
下面的代码是设置曲线图可框选。
/**** 框选曲线图,获得选中数据 ****/
//数据多选
ui->widget->graph(0)->setSelectable(QCP::SelectionType::stMultipleDataRanges);
//选择框模式:无
ui->widget->setSelectionRectMode(QCP::SelectionRectMode::srmNone);
//选框黑色虚线
ui->widget->selectionRect()->setPen(QPen(Qt::black,1,Qt::DashLine));
ui->widget->selectionRect()->setBrush(QBrush(QColor(0,0,100,50)));
//设置可框选
ui->widget->setInteraction(QCP::iRangeDrag,false);//取消拖动
ui->widget->setSelectionRectMode(QCP::SelectionRectMode::srmSelect);
//修改多选按键,默认Ctrl。这个函数是设置选中数据的方式
//customPlot->setMultiSelectModifier(Qt::KeyboardModifier::ControlModifier);
//滚动缩放、图表可选、多选
//ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectPlottables| QCP::iMultiSelect);//
qDebug()<<"ok0";
ui->widget->replot();
有几个关键类:第一,动作类QAction;第二,菜单类QMenu。
动作类就是菜单内的具体操作;菜单分为一级菜单,二级菜单。
菜单类可以添加动作,可以添加下级菜单;
ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);必须添加,响应右键操作。
通过connect给Action定义具体操作。
/**** 设置鼠标右键菜单 ****/
//主菜单的设置
//初始化动作
QAction * curveAction1 = new QAction("btnFirstAction",this);
QAction * curveAction2 = new QAction("btnSecondAction",this);
//初始化菜单
QMenu * curveMenu = new QMenu(this);
//动作添加到菜单
curveMenu->addAction(curveAction1);
curveMenu->addAction(curveAction2);
//子菜单的设置
QMenu *childMenu = new QMenu();
childMenu->setTitle("df");//给子菜单取名字
QAction *delfile = new QAction(childMenu);
delfile->setText("删除");
QAction *addfile = new QAction(childMenu);
addfile->setText("添加");
childMenu->addAction(delfile);
childMenu->addAction(addfile);
curveMenu->addMenu(childMenu);
//给动作设置信号槽
connect( curveAction1, &QAction::triggered, [=]()
{
qDebug()<<"I'm btnFirstAction";
});
connect( curveAction2, &QAction::triggered, [=]()
{
qDebug()<<"I'm btnSecondAction";
});
//给曲线图设置上下文菜单策略,鼠标右键点击曲线图时会发送一个void QWidget::customContextMenuRequested(const QPoint &pos)信号
ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
//给信号设置相应的槽函数
connect(ui->widget,&QLabel::customContextMenuRequested,[=](const QPoint &pos)
{
qDebug()<<pos;//参数pos用来传递右键点击时的鼠标的坐标,这个坐标一般是相对于控件左上角而言的
curveMenu->exec(QCursor::pos());
});
手机扫一扫
移动阅读更方便
你可能感兴趣的文章