先看一个Qcharts的简单demo
Qcharts是QT自带的组件,不需要另外添加文件。
打开QT Creator,新建一个工程,命名可以参考下图:
基类选择QWidget:
.pro文件中添加charts模块
main.cpp源码:
#include "widget.h"
#include <QApplication>
// 包含line chart需要的头文件
#include <QChartView>
#include <QLineSeries>
// 引用命名空间
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//绘制折线图采用的是QLineSeries序列类,两点间只是简单的用直线连接。
QLineSeries *series = new QLineSeries();
// 添加实验数据,可以用 append 方法 或者 << 操作符
series->append(0,2);
series->append(QPointF(2,6));
series->append(3,8);
series->append(7,9);
series->append(11,3);
*series << QPointF(11,2) << QPointF(15,5) << QPointF(18,4) << QPointF(19,2);
QChart *chart = new QChart();
// 将图例隐藏
chart->legend()->hide();
// 关联series,这一步很重要,必须要将series关联到QChart才能将数据渲染出来:
chart->addSeries(series);
// 开启OpenGL,QLineSeries支持GPU绘制,Qt其他有的图表类型是不支持的。
series->setUseOpenGL(true);
// 创建默认的坐标系(笛卡尔坐标)
chart->createDefaultAxes();
// 设置图表标题
chart->setTitle(QStringLiteral("Qt line chart example"));
QChartView *view = new QChartView(chart);
// 开启抗锯齿,让显示效果更好
view->setRenderHint(QPainter::Antialiasing);
view->resize(400,300);
// 显示图表
view->show();
return a.exec();
}
运行效果:
上面是一个折线图的示例。
QLineSeries类以折线图的形式显示数据。
折线图用于将信息显示为由直线连接的一系列数据点。
基本的创建折线的步骤如下:
// 逐一添加数据点
QLineSeries* series = new QLineSeries();
series->append(0, 6);
series->append(2, 4);
...
chart->addSeries(series);
先new一个QLineSeries,再逐一添加数据点,最后把实例化的QLineSeries与chart关联起来
我们可以把series单独看成一条图线,chart看成一个画布或坐标系,两个组合起来才是完整的图形。
注意append是逐一往后添加数据点,就是说存在添加的先后顺序。
上面的demo程序中出现了三个重要的class,分别是QLineSeries,QChart,QChartView
QChartView是一个独立的小部件,可以显示图表。
QLineSeries类以折线图的形式显示数据。折线图用于将信息显示为由直线连接的一系列数据点。
QChart类管理图表系列、图例和轴的图形表示。 为了简单地在布局中显示图表,可以使用类QChartView来代替QChart。
折线用QLineSeries,曲线用QSplineSeries
QSplineSeries是用来绘制光滑曲线的类,它在两点之间连线时采用插值算法(插值就是通过一系列已知的数据点,来"猜测"未知点),绘制折线图采用的是QLineSeries序列类,两点间只是简单的用直线连接。
上面的示例我们改一下
QLineSeries *series = new QLineSeries();
改成QSplineSeries *series = new QSplineSeries();
新增头文件#include <QSplineSeries>
运行效果:
动态刷新随机点
上节是直接在程序中用QChartView显示chart
这节看怎么在ui设计界面添加QChartView
找到Widget部件拉过去,调整好大小
添加的Widget控件不能显示chart图表,需要将其提升为QchartView。
具体操作:拖一个Widget控件到界面,右键Widget->提升为, 在提升的类名称一栏填:QChartView,头文件可以不管,会自动生成(如下图),然后点添加再点提升。
.pro文件中添加charts模块
widget.h文件中需要添加using namespace QtCharts;
或者QT_CHARTS_USE_NAMESPACE
都可以
widget.h文件源码:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtCharts/QSplineSeries>
#include <QtCharts>
#include <QDateTime>
using namespace QtCharts;
// 引用命名空间
//QT_CHARTS_USE_NAMESPACE
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//声明QChart的实例,QSplineSeries的实例
QChart *chart; //画布
QSplineSeries *series1; //线
QDateTimeAxis *axisX; //轴
QValueAxis *axisY;
QTimer *timer; //计时器
void drawLine();
void initChart();
public slots:
//声明timer的槽函数
void timerDeal();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
main.cpp维持默认
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp源码:
#include "widget.h"
#include "ui_widget.h"
// 包含line chart需要的头文件
//#include <QChartView>
//#include <QLineSeries>
//#include <QSplineSeries>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//初始化QChart
initChart();
//设置timer
timer = new QTimer();//创建定时器
timer->setInterval(400);//设置定时周期
connect(timer,SIGNAL(timeout()),this,SLOT(timerDeal()));//连接定时器与定时溢出处理槽函数
timer->start();
}
Widget::~Widget()
{
delete ui;
}
//实现QChart的初始化函数
void Widget::initChart()
{
chart = new QChart();//初始化QChart的实例
series1 = new QSplineSeries();//初始化QSplineSeries的实例
axisX = new QDateTimeAxis();//初始化X轴、Y轴
axisY = new QValueAxis();
//设置曲线的名称
series1->setName("series1");
chart->legend()->hide();//隐藏图例
//把曲线添加到QChart的实例chart中
chart->addSeries(series1);
//设置X轴显示的范围
axisX->setMin(QDateTime::currentDateTime().addSecs(-60*1));
axisX->setMax(QDateTime::currentDateTime().addSecs(0));
axisX->setFormat("hh:mm:ss"); //设置时间显示格式
axisY->setMin(0); //设置Y轴范围
axisY->setMax(10);
//axisY->setRange(0,100); //也可以用这个设置范围
//设置坐标轴上的格点
axisX->setTickCount(5);
axisY->setTickCount(10);
//设置坐标轴显示的名称
axisX->setTitleText("X轴");
axisY->setTitleText("Y轴");
//设置坐标轴的颜色,粗细,设置网格不显示
axisY->setLinePenColor(QColor(Qt::darkBlue));
axisY->setGridLineColor(QColor(Qt::darkBlue));
axisY->setGridLineVisible(false);
QPen penY1(Qt::darkBlue,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);
axisY->setLinePen(penY1);
//把坐标轴添加到chart中,
//addAxis函数的第二个参数是设置坐标轴的位置,
//只有四个选项,下方:Qt::AlignBottom,左边:Qt::AlignLeft,右边:Qt::AlignRight,上方:Qt::AlignTop
chart->addAxis(axisX,Qt::AlignBottom);
chart->addAxis(axisY,Qt::AlignLeft);
//把曲线关联到坐标轴
series1->attachAxis(axisX);
series1->attachAxis(axisY);
//把chart显示到窗口上
ui->widget->setChart(chart);
ui->widget->setRenderHint(QPainter::Antialiasing); //设置抗锯齿
}
//实现画线函数,动态更新
void Widget::drawLine()
{
//每增加一个点改变X轴的范围,实现曲线的动态更新效果
QDateTime bjtime=QDateTime::currentDateTime();
chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1));//系统当前时间的前一秒
chart->axisX()->setMax(QDateTime::currentDateTime().addSecs(0));//系统当前时间
//当曲线上最早的点超出X轴的范围时,剔除最早的点,
// if(series1->count()>119)
// {
// series1->removePoints(0,series1->count()-119);
// }
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));//设置种子
int Y1=qrand()%9;//随机生成0到9的随机数
//增加新的点到曲线末端
series1->append(bjtime.toMSecsSinceEpoch(),Y1);
}
//实现timer的槽函数
void Widget::timerDeal()
{
//定时画曲线
drawLine();
}
效果:
对上面的例程我们需要了解的:
1、代码中没有定义chart 的整个图占的大小,所以ui里添加的Widget控件可以直接通过拉动四个角调整大小。
比如下图,就是只在ui里调整了Widget控件使其高度缩小的效果
2、对比一下不开抗锯齿的情况:
即ui->widget->setRenderHint(QPainter::Antialiasing);
这句去掉
3、为了显示图表,除了Widget控件可以提升为QchartView,还有Graphics View组件也可以提升为QchartView(目前只测试了这两个可以提升QchartView,应该还有别的)
相关方法
QChart类方法
// 1.添加自定义坐标轴 Qt::AlignLeft 左侧X轴 Qt::AlignBottom 下端Y轴
void addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
// 2.设置默认坐标轴(QChart为根据系列上的数据,创建合适的坐标轴,数据中最小/最大的x值为坐标的x的范围,数据中最小/最大的y值为坐标的y的范围)
void createDefaultAxes()
// 3.移除坐标轴
void removeAxis(QAbstractAxis *axis)
// 3.添加单个系列
void addSeries(QAbstractSeries *series)
// 4.移除单个系列
void QChart::removeSeries(QAbstractSeries *series)
// 5.移除全部系列
void QChart::removeAllSeries()
// 6.平移
void scroll(qreal dx, qreal dy)
// 7.设置外边距,通过设置负数可以是图表外面的空白减小 QMargins m(-10,-10,-10,-10);
void setMargins(const QMargins &margins)
// 8.设置图表绘制的位置,注意:不包含坐标轴 QRectF r(0,0,600,400); 此时将看不到Y轴坐标轴
void setPlotArea(const QRectF &rect)
// 9.设置标题
void setTitle(const QString &title)
// 9.1设置绘制标题的画刷
void setTitleBrush(const QBrush &brush)
// 9.2设置标题的字体
void setTitleFont(const QFont &font)
// 10.放大/缩小坐标轴的范围 以图表的中心点开始放大/缩小
void zoom(qreal factor)
// 11.获取图表的图例,即系列的名称 通过 QLegend.hide() 可隐藏图表中所有的图例
QLegend *QChart::legend() const
QValueAxis类方法
// 1 设置范围
void setRange(qreal min, qreal max)
void setMax(qreal max)
void setMin(qreal min)
// 2 设置网格划分类型 QValueAxis::TicksDynamic 按固定值划分 QValueAxis::TicksFixed 按份来划分(默认)
void setTickType(QValueAxis::TickType type);
// 3 设置主要刻线线 设置为11,则按范围等分为10份, 在 QValueAxis::TicksFixed 时生效
void setTickCount(int count)
// 4 设置次要刻线, 设置为6,即给每个主刻度线在等分为5份 共 10 * 5 50份 在 QValueAxis::TicksFixed 时生效
void setMinorTickCount(int count)
// 5 按值设置刻度线,每两条刻度线间隔的值为设置的值,在 QValueAxis::TicksDynamic 时生效
void setTickInterval(qreal insterval)
// 6 隐藏刻度线
void QAbstractAxis::hide()
// 7 设置主要刻度线的颜色
void setGridLineColor(const QColor &color)
// 8 设置主要刻度线的画笔
void setGridLinePen(const QPen &pen)
// 9 设置主要刻度线的可见性
void setGridLineVisible(bool visible = true)
// 10 设置轴线的颜色
void setLinePenColor(QColor color)
// 11 设置轴线的可见性
void setLineVisible(bool visible = true)
// 12 设置标题
void setTitleText(const QString &title)
void setTitleFont(const QFont &font)
void setShadesColor(QColor color)
void setShadesPen(const QPen &pen)
void setShadesBrush(const QBrush &brush)
void setTitleVisible(bool visible = true)
// 13 设置标签
void setLabelsAngle(int angle)
void setLabelsColor(QColor color)
void setLabelsFont(const QFont &font)
void setLabelFormat(const QString &format) // ("%d") %d为十进制显示
QAbstractSeries类下的QXYSeries方法
QAbstractSeries为系列的基类,其下又分为 QXYSeries类(折线图、样条曲线图、散点图的基类)、QPieSeries类(饼状图)、QAbstractBarSeries类(条状图)等
-QAbstractSeries
---QXYSeries
-----QLineSeries 折线图
-------QSplineSeries样条曲线图 // 相比较于QLineSeries,更加平滑,同时更加耗时,大概为2.5倍时间,不过总时间很小(10000个点0.3ms),基本可忽略
-----ScatterSeries 散点图
---QPieSeries
---QAbstractBarSeries
方法:
// 1.1 添加单个数据 不推荐
void append(qreal x, qreal y)
// 1.2 添加单个数据 不推荐
void append(const QPointF &point)
// 1.3 添加多个数据 不推荐
void append(const QList<QPointF> &points)
// 1.4 替换单个数据 不推荐
void replace(qreal oldX, qreal oldY, qreal newX, qreal newY)
// 1.5 替换多个数据 不推荐
void replace(QList<QPointF> points)
// ***1.6 替换多个数据 极力推荐 (使用replace时,将不需要使用clear())
void replace(QVector<QPointF> points)
// 2 在系列中根据索引获取坐标
const QPointF &at(int index) const
// 3 插入某个点
void insert(int index, const QPointF &point)
// 4 获取画刷
QBrush brush() const
// 5 清空
void clear()
// 6 获取颜色 折线图、样条曲线图的线条颜色 散点图的填充颜色
virtual QColor color() const
// 7 获取点的数量
int count() const
// 8 获取绘制轮廓的笔
QPen pen() const
// 9 获取所有点
QVector<QPointF> pointsVector() const
// 10 该系列点是否绘制(是否可见) 注意:设置为false时,看不见凸出的点,但是线仍然可以看见
bool pointsVisible() const
// 11 设置绘制点的画刷
virtual void setBrush(const QBrush &brush)
// 12 设置绘制点的笔
virtual void setPen(const QPen &pen)
// 13 设置绘制线的画刷 折线图、样条曲线图的线条颜色 散点图的填充颜色
virtual void setColor(const QColor &color)
// 14.1 设置点的标签,每个点都会被设置
void setPointLabelsFormat(const QString &format)
// 14.2 设置裁剪,超过图表区域部分会被裁剪
void setPointLabelsClipping(bool enabled = true)
// 14.3 设置点的标签的颜色
void setPointLabelsColor(const QColor &color)
// 14.4 设置点的标签的字体
void setPointLabelsFont(const QFont &font)
// 14.5 设置点的标签的可见
void setPointLabelsVisible(bool visible = true)
// 15 绑定坐标轴 需要连续绑定X轴、Y轴,而且要与QChart绑定同一组坐标轴
bool QAbstractSeries::attachAxis(QAbstractAxis *axis)
小提示:对于代码中不清楚的类或方法,都可以选定后按F1进入帮助文档查看