qt绘制实时曲线_qt 实时绘制曲线 - CSDN
精华内容
参与话题
  • Qt Charts 动态实时绘制各种曲线

    万次阅读 热门讨论 2020-10-20 19:44:02
    Qt Charts发布之前,Qt比较著名两个画图插件是 qwt和Qcustom, 其中Qcustom较轻量,只需要在project 中包含qcustomplot.h 和qcustomplot.cpp 几乎就可以使用。 相比Qcustom,qwt功能更为强大,但是它的安装十分...

    在Qt Charts发布之前, Qt比较著名两个画图插件是 qwt和Qcustom, 其中Qcustom较轻量,只需要在project 中包含qcustomplot.h 和 qcustomplot.cpp 几乎就可以使用。
    相比Qcustom,qwt功能更为强大,但是它的安装十分麻烦,阻挡了很多人(包括我)的使用。
    但是qwt只是对静态图表的表示非常不错,动态曲线性能并不突出。如果只是静态绘图,或者动态绘制的点并不多,继续用qwt甚至Qcustom完全没问题。
    但是如果是新入手Qt绘图,用Qt charts显然是更好的选择,因为它在各方面都比前两者要好,并且也易于使用。
    并且qml也支持charts,qml的渲染默认用GPU,成长性更好。
    如果你在安装Qt的时候,选择了Qt charts部分,那么在Qt中使用charts 只需要 在 .pro文件中

    QT += charts


    并且在程序的开头加上一句 using namespace Qtcharts或者一个宏 QT_CHARTS_USE_NAMESPACE 

    进入主题: 动态实时折线图绘制

    动态绘图,也就是说折线随着横坐标的增长而实时变化。

    从这一秒和上一秒的变化看来,就是坐标轴不动,整个图像往前移了一个单位,然后在空出的最后一个位置增加了一个新的点。

    想一下,只要你的显示器不能够随着横坐标的增长变宽,上面说的就是不得不做的事情。或者除非你不把最前面的那个点淘汰掉,但是那样的话,你的点只有增,没有删,随着时间的增长,点越来越多,曲线最后只会挤成一团,啥也看不清。
    【多说一句,从相对的角度来说,既然可以把图像往前移一个单位,当然也可以坐标轴往后移一个单位,两者造成的结果当然是一样的。
    Qt有一个函数scroll可以实现后者的功能,它有两个参数,可以设置每次x、y轴向右和向上滚动的距离。但是scroll函数绘制坐标轴感觉很奇怪……真的有一种在滚的感觉,看起来很难受,具体可以看Qt欢迎界面里面的一个示例子dynamicspline】


    Qt charts中,可以主要一下几个类: QChart 和 QChartView,QChart是用什么画,差不多画笔的意思,QChartView是在什么上画,差不多画布的意思。

     m_chartView = new QChartView(m_chart,this);//画布
        m_chart = m_chartView->chart();//画笔

    画笔绑在画布上,就新建了一个QChartView 和一个 QChart 指针。
     类 Series 是用来添加数据的对象(可以理解为一个集合)。常见的 QLineSeries,折线类,画出来的先棱角更强,QSplineSeries,曲线类,画出来更平滑,QScatterSeries,点类,画出来是一个个单独的点。Qt文档对这些类都有很详细的说明,并配有图画。
    类似于QChart 、QChartView、Series ,还有QValueAxis类(数值类型的坐标轴)等等,不再啰嗦,下面的代码里都有。并且有很详细的注释,想学的朋友一定仔细看一遍肯定能看明白。
     

     ui->setupUi(this);
        m_chart = new QChart();
        m_chartView = new QChartView(m_chart,this);//画布
        m_chart = m_chartView->chart();//画笔
        m_chartView->setRubberBand(QChartView::NoRubberBand);  //矩形缩放
    
        m_chartView->setRenderHint(QPainter::Antialiasing); //设置抗锯齿
        m_chartView->resize(600, 600);   //画布大小
        m_chartView->setContentsMargins(0,0,0,0);
        m_chartView->show(); //显示
        //设置x坐标轴
        axisX = new QValueAxis;
        axisX->setRange(0, 100);  //范围
        axisX->setLabelFormat("%d"); //图例的格式  %d为十进制显示
        axisX->setGridLineVisible(true);//网格
        axisX->setTickCount(10);   //主要刻度
    //	axisX->setMinorTickCount(5);//小刻度
        axisX->setTitleText("time/(s)");//标题
    //设置y坐标轴
        axisY = new QValueAxis;
        axisY->setRange(0, 20);
        axisY->setLabelFormat("%d");
        axisY->setGridLineVisible(true);
        axisY->setTickCount(10);//轴上有多少个标记数目
        axisY->setMinorTickCount(5);//主要刻度之间有多少网格线
        axisY->setTitleText("altitude/(%)");
    
        m_chart->addAxis(axisX, Qt::AlignBottom);  //将坐标轴加到chart上,居下
        m_chart->addAxis(axisY, Qt::AlignLeft);//居左
    
       //m_chart->setTitle("example of chart");   //设置图表标题
        //m_chart->setAnimationOptions(QChart::SeriesAnimations);  //曲线动画模式,不能启用这一项或是选择这个选项,这个会导致曲线闪烁
        m_chart->legend()->setVisible(true);  //设置图例可见
        m_chart->legend()->setLayoutDirection(Qt::LeftToRight);
        m_chart->legend()->setAlignment(Qt::AlignLeft);
      //生成一小段数据列表用作绘图初始数据
        QList<QPointF> mydata1;
        for (int i = 0; i <100; i++)
        {
            mydata1.append(QPointF(i, 0.1*i));
        }
        addSeries(mydata1); //增加一条曲线,数据集为mydata1
        connectMarkers();  //将曲线与图例连接起来,可以勾选进行显示与隐藏
    
        m_chart->setAxisX(axisX, m_serieslist.first());  //将x和y坐标轴与第一条曲线连接
        m_chart->setAxisY(axisY, m_serieslist.first());
        timeId = startTimer(1000);    //qobject中的函数,设置定时器时间间隔

    线都是又一系列的点构成的,线是点的集合,容器里在包含一系列的线,用画笔绘制在画布上,这就是QChart

    void Widget::addSeries(QList<QPointF> &data)  //用于新增曲线
    {
    
        QSplineSeries *series = new QSplineSeries(this);//平滑曲线的集合
        m_serieslist.append(series);//将曲线加到曲线列表中进行管理
        series->setName(QString("line " + QString::number(m_serieslist.count()))); //设置曲线对应的名字,用于图例显示
        series->append(data);  //将数据加到曲线中
        m_chart->addSeries(series);//将曲线增入chart中
        axisX->setRange(0, series->count());  //坐标轴初始范围为图表中的数据数。 这个在绘制多条曲线中需注释
        QPen splinePen ,linePen;
        splinePen.setBrush(Qt::red);
        splinePen.setColor(Qt::red);
        series->setPen(splinePen);
    
        QSplineSeries *lineSeries = new QSplineSeries(this);//折线类点的集合
        lineSeries->setName(QStringLiteral("折线"));
        QList<QPointF> lineData;
        QPoint newPoint;
        foreach (QPointF point, data) {
           newPoint.setX(point.x() * 1.5);
           newPoint.setY(point.y() * 1.5);
           lineData.append(newPoint);
        }
    //    lineSeries->append(0,0);
    //    lineSeries->append(10,10);
    //    lineSeries->append(15,15);
        lineSeries->append(lineData);
        linePen.setBrush(Qt::yellow);
        lineSeries->setPen(linePen);
        m_serieslist.append(lineSeries);
        m_chart->addSeries(lineSeries);
    
    }

    的思想

     

    利用定时器定时刷新不同的点,来实时绘制动态曲线

    void Widget::timerEvent(QTimerEvent *event)    //定时器事件的重构
    {
        if (event->timerId() == timeId)//定时器时间到,模拟数据填充
        {
            static QTime dataTime(QTime::currentTime());
            long int eltime = dataTime.elapsed();  //上次start经过毫秒数
            static int lastpointtime = 1;
            int size = (eltime - lastpointtime);//数据个数
            qDebug() << "size-->" << size;
            foreach (QSplineSeries  *splineSeries, m_serieslist) {
                if (splineSeries->isVisible())
                {
                    QVector<QPointF> olddata = splineSeries->pointsVector();
                    olddata.append(QPointF(lastpointtime +olddata.count(), lastpointtime*0.3));//填充数据--->>相当于每一分钟增加一点
                    axisX->setRange(0, lastpointtime + splineSeries->count());//设置x坐标轴
                    //后期需更改为一开始固定,只有当数据个数超出坐标轴范围时坐标轴开始扩展。
                    splineSeries->replace(olddata);
                    lastpointtime++;
                }
            }
    
        }
    }
    

    效果图

     

    源码请在链接在找到源码

    展开全文
  • 1.首先是掌握qtchart的基本使用,封装一个属于自己的绘图类: Mychart.h #pragma once #ifndef CHART_H #define CHART_H #include &lt;QtCharts/QChart&gt; #include&lt;QtCharts\QChartView&gt; ...

    1.首先是掌握qtchart的基本使用,封装一个属于自己的绘图类:
    Mychart.h

    #pragma once
    #ifndef CHART_H
    #define CHART_H
    
    #include <QtCharts/QChart>    
    #include<QtCharts\QChartView>   //两个基本模块
    #include<QPointF>     //点类
    #include<QList>         //列表
    #include <QtCore/QTimer>   //定时器
    
    QT_CHARTS_BEGIN_NAMESPACE    
    class QSplineSeries;
    class QValueAxis;                 //引入这两个类而免于引入整个头文件的方法
    QT_CHARTS_END_NAMESPACE
    
    QT_CHARTS_USE_NAMESPACE   //使用qtchart需要加入这条语句
    
    //![1]
    class Chart : public QChart
    {
    	Q_OBJECT
    public:
    	Chart(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
    	QChartView *m_chartView;   //因为布局时其它函数会访问这个画布,所以设为public
    	virtual ~Chart();
    	QList<QPointF> setdata();    //预留这个函数作为一个设置图表数据的接口,将外界数据传给图表
    public slots:
    //	void handleTimeout();
    //几个操作数据的槽函数
    	void addSeries(QList<QPointF> &data);     //新增一条曲线
    	void removeSeries();                            //移出一条曲线
    	void connectMarkers();                   //连接图线与图例
    	void disconnectMarkers();               //断开图线与图例
    	void handleMarkerClicked();           //占击图例时的处理函数
    protected:
    	void timerEvent(QTimerEvent *event)Q_DECL_OVERRIDE;  //定时器触发事件,重构
    private:
    	QTimer m_timer;     //定时器指针
    
    	QChart * m_chart;     //图表组件,可理解为画笔,用它画曲线
    	QList<QSplineSeries *> m_serieslist;   //曲线列表,splineseries为光滑曲线
    
    	QSplineSeries *m_series;     //曲线指针
    	QStringList m_titles;             //标题
    	QValueAxis *axisX;             //x坐标轴
    	QValueAxis *axisY;             //y坐标轴
    	
    	qreal m_step;                  
    	qreal m_x;
    	qreal m_y;
    };
    //![1]
    
    #endif /* CHART_H */
    

    MyChart.cpp

    #include "MyChart.h"
    #include <QtCharts/QAbstractAxis>
    #include <QtCharts/QSplineSeries>
    #include <QtCharts/QValueAxis>
    #include <QtCore/QTime>
    #include <QtCore/QDebug>
    #include <QPen>
    #include<QPainter>
    #include<QtCharts\QLegendMarker>
    #include<qmath.h>
    
    int timeId;
    
    Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags) :QChart(QChart::ChartTypeCartesian, parent, wFlags)
    {
    	m_chart = new QChart;
    	m_chartView = new QChartView(m_chart);
    	m_chartView->setRubberBand(QChartView::RectangleRubberBand);  //矩形缩放
    	//设置x坐标轴
    	axisX = new QValueAxis;
    	//axisX->setRange(0, 1000);  //范围
    	axisX->setLabelFormat("%d"); //图例的格式  %d为十进制显示
    	axisX->setGridLineVisible(true);//网格
    	//axisX->setTickCount(11);   //主要刻度
    //	axisX->setMinorTickCount(5);//小刻度
    	axisX->setTitleText("time/(s)");//标题
    //设置y坐标轴
    	axisY = new QValueAxis;
    	axisY->setRange(0, 20);
    	axisY->setLabelFormat("%d");
    	axisY->setGridLineVisible(true);
    	axisY->setTickCount(10);
    	axisY->setMinorTickCount(5);
    	axisY->setTitleText("altitude/(%)");
    
    	m_chart->addAxis(axisX, Qt::AlignBottom);  //将坐标轴加到chart上,居下
    	m_chart->addAxis(axisY, Qt::AlignLeft);//居左
    
       //m_chart->setTitle("example of chart");   //设置图表标题
    	//m_chart->setAnimationOptions(QChart::SeriesAnimations);  //曲线动画模式,不能启用这一项或是选择这个选项,这个会导致曲线闪烁
    	m_chart->legend()->setVisible(true);  //设置图例可见
      //生成一小段数据列表用作绘图初始数据
    	QList<QPointF> mydata1;
    	for (int i = 0; i <100; i++)
    	{
    		mydata1.append(QPointF(i, 0.01*i));
    	}
    	addSeries(mydata1); //增加一条曲线,数据集为mydata1
       connectMarkers();  //将曲线与图例连接起来,可以勾选进行显示与隐藏
       
    	m_chart->setAxisX(axisX, m_serieslist.first());  //将x和y坐标轴与第一条曲线连接
    	m_chart->setAxisY(axisY, m_serieslist.first());
    	timeId = startTimer(500);    //qobject中的函数,设置定时器时间间隔
    
    }
    
    Chart::~Chart()
    {
    
    }
    
    
    void Chart::addSeries(QList<QPointF> &data)  //用于新增曲线
    {
    
    	QSplineSeries *series = new QSplineSeries();
    	m_serieslist.append(series);//将曲线加到曲线列表中进行管理
    	series->setName(QString("line " + QString::number(m_serieslist.count()))); //设置曲线对应的名字,用于图例显示
    	series->append(data);  //将数据加到曲线中
    	m_chart->addSeries(series);//将曲线增入chart中
    	axisX->setRange(0, series->count());  //坐标轴初始范围为图表中的数据数。 这个在绘制多条曲线中需注释
    
    }
    
    void Chart::removeSeries()  //移除一条曲线
    {
    	// Remove last series from chart
    	if (m_serieslist.count() > 0) {
    		QSplineSeries *series = m_serieslist.last();
    		m_chart->removeSeries(series);
    		m_serieslist.removeLast();
    		delete series;
    	}
    }
    
    void Chart::connectMarkers()  //将槽函数与图例的鼠标点击事件连接起来
    {
    	// Connect all markers to handler
    	foreach(QLegendMarker* marker, m_chart->legend()->markers()) {
    		// Disconnect possible existing connection to avoid multiple connections
    		QObject::disconnect(marker, &QLegendMarker::clicked, this, &Chart::handleMarkerClicked);
    		QObject::connect(marker, &QLegendMarker::clicked, this, &Chart::handleMarkerClicked);
    	}
    }
    
    void Chart::disconnectMarkers()
    {
    	foreach(QLegendMarker* marker, m_chart->legend()->markers()) {
    		QObject::disconnect(marker, &QLegendMarker::clicked, this, &Chart::handleMarkerClicked);
    	}
    }
    
    void Chart::handleMarkerClicked()//图例点击事件
    {
    	QLegendMarker* marker = qobject_cast<QLegendMarker*> (sender());
    	Q_ASSERT(marker);
    	//![3]
    
    	//![4]
    	switch (marker->type())
    		//![4]
    	{
    	case QLegendMarker::LegendMarkerTypeXY:
    	{
    		//![5]
    		// Toggle visibility of series
    		marker->series()->setVisible(!marker->series()->isVisible());
    
    		// Turn legend marker back to visible, since hiding series also hides the marker
    		// and we don't want it to happen now.
    		marker->setVisible(true);
    		//![5]
    
    		//![6]
    		// Dim the marker, if series is not visible
    		qreal alpha = 1.0;
    
    		if (!marker->series()->isVisible()) {
    			alpha = 0.5;
    		}
    
    		QColor color;
    		QBrush brush = marker->labelBrush();
    		color = brush.color();
    		color.setAlphaF(alpha);
    		brush.setColor(color);
    		marker->setLabelBrush(brush);
    
    		brush = marker->brush();
    		color = brush.color();
    		color.setAlphaF(alpha);
    		brush.setColor(color);
    		marker->setBrush(brush);
    
    		QPen pen = marker->pen();
    		color = pen.color();
    		color.setAlphaF(alpha);
    		pen.setColor(color);
    		marker->setPen(pen);
    
    		//![6]
    		break;
    	}
    	default:
    	{
    		qDebug() << "Unknown marker type";
    		break;
    	}
    	}
    }
    
    QList<QPointF> Chart::setdata()  //设置图表数据的函数接口
    {
    	QList<QPointF> datalist;
    	for (int i = 0; i < 500; i++)
    		datalist.append(QPointF(i, i*0.01));
    	return datalist;
    }
    
    void Chart::timerEvent(QTimerEvent *event)    //定时器事件的重构
    {
    	if (event->timerId() == timeId)//定时器时间到,模拟数据填充
    	{
    		static QTime dataTime(QTime::currentTime());
    		long int eltime = dataTime.elapsed();  //经过的时间
    		static int lastpointtime = 1;
    		int size = (eltime - lastpointtime);//数据个数
    		qDebug() << "size-->" << size;
    		if (isVisible())
    		{
    
    			QVector<QPointF>olddata=m_serieslist.first()->pointsVector();
    			olddata.append(QPointF(lastpointtime +olddata.count(), lastpointtime*0.3));//填充数据
    			axisX->setRange(0, lastpointtime + m_serieslist.first()->count());//设置x坐标轴
    			//后期需更改为一开始固定,只有当数据个数超出坐标轴范围时坐标轴开始扩展。
    			m_serieslist.first()->replace(olddata);
    			lastpointtime++;
    		}
    	}
    }
    
    

    关于绘制动态曲线,关键就是在设置好初始画布后进行曲线数据的更新,以及坐标轴的更新。
    数据更新可以是定时,也可以新建增加数据的槽函数,当接收到外部数 据时,触发信号进行曲线更新。

    坐标轴更新是用于扩展坐标轴以适应曲线。

    动态绘制曲线的核心是数据点个数变化,数据个数一定的情况下,是通过进行数据更新通过平移以淘汰最开始的数据。
    同时要相应地扩展坐标轴或改变坐标轴。

    做上位机界面时,要绘制从下位机收到数据的曲线,需要有一个接收和更新数据的buffer或是datalist。 datalist可方便地去数据头和新增数据。可以作为首选。
    收到的数据作为y, (count,data)作为新增的数据点。

    展开全文
  • 随机生成一组数据,QT用Qpainter绘制实时曲线图最简单的折线图
  • QT5 实时曲线绘制

    2020-07-25 23:32:33
    QT5中绘制实时曲线,利用随机数据产生数据绘制,最长记录时间为30分钟。
  • Qt实现实时曲线

    千次阅读 2017-08-25 08:34:53
    Qt实现实时曲线

    Qt实现曲线的方式有多种方式,第三方库也有不少,例如QtChart,QCustomPlot,Qwt,chartDirector或者利用js也可以实现。对于不用库的优缺点就不在这里说明了。本例子只是利用Qt的QPainter实现。可以支持4.x,5.x(3.x应该也可以没有测试)。
    这里写图片描述
    使用如下
    m_line = new CRealTimeLine;
    m_line->setDrawStartLeft(false);
    m_line->addDataList(datalist);
    QLinearGradient liner;
    liner.setColorAt(0,QColor(“#9DCEFF”));
    liner.setColorAt(1,QColor(“#FFFFFF”));
    m_line->setInterval(5);
    m_line->setBackColor(liner);
    setCentralWidget(m_line);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(5000);
    

    头文件

    
    ifndef CREALTIMELINE_H 
    
    define CREALTIMELINE_H
    
     #include <QWidget> 
    include <QList>
     #include <QFont>
      #include <QDateTime>
    
     #include "qmath.h"
    
    class CRealTimeLine : public QWidget
    {
        Q_OBJECT
    
    public:
        CRealTimeLine(QObject *parent = NULL);
        ~CRealTimeLine();
    
        void setXLabels(QStringList labellist);
        void setYLabels(QStringList labellist);
        void setDrawStartLeft(bool startleft = true); //默认从左侧
        void addDataList(QList<float> dlist);
        void addDataList(float value);
        void removeDatas(); //清除数据
        void setBackColor(QLinearGradient linegradent);
        void setLineColor(QColor color);
        void setMaxValue(int max);
        void setPrefixText(QString text);
        void setInterval(int interval);
    
    
    private:
        void initdata();
    
    private:
        QPainterPath drawGridding(); //网格
        QPainterPath drawRectPath(); //边框
        QPainterPath drawXYScalePath(); //x,y刻度
        void drawXLabel(QPainter &painter);
        void drawYLabel(QPainter &painter);
        QPainterPath drawLineLeftPath();  //左侧开始画线
        QPainterPath drawLineRigthPath();  //右侧开始画线
        QPainterPath drawBack(QPainter &painter);
        void drawText(QPainter &painter);  //默认最后一个值
        void drawLine(QPainter &painter);
    
    private:
        void paintEvent( QPaintEvent * event );
    
    private:
        QPointF m_originpoint;  //原点所在位置
        int m_griddingcount_x,m_griddingcount_y; //网格个数
        QStringList m_xlabellist,m_ylabellist;
        int m_count; //点的个数
        QList<float> m_datelist; //数据
        bool m_isstartleft; //画的方式,从左侧还是右侧 默认左侧
        int m_ymax,m_ymin;
        QList<QColor> m_defaultcolors;
        QLinearGradient m_backlinegradent; //背景
        QColor m_linecolor;
        QString m_textstr;
        QDateTime m_olddateime;
        int m_interval;
    
    };
    
    endif // CREALTIMELINE_H
    
    `cpp文件
    

    include “crealtimeline.h”

    include

    CRealTimeLine::CRealTimeLine(QObject *parent)
    //: QWidget(parent)
    {
    m_isstartleft = false;
    m_count = 30*60; //默认30分钟的数据。一秒一个
    m_ymax = 100;
    m_ymin = 0;
    m_defaultcolors.append(QColor(“red”));
    m_defaultcolors.append(QColor(“blue”));
    m_defaultcolors.append(QColor(“yellow”));
    m_defaultcolors.append(QColor(“green”));
    m_linecolor = QColor(“green”);
    m_olddateime = QDateTime::currentDateTime();
    m_interval = 1;
    }

    CRealTimeLine::~CRealTimeLine()
    {

    }
    void CRealTimeLine::setXLabels( QStringList labellist )
    {
    m_xlabellist.clear();
    m_xlabellist = labellist;
    }

    void CRealTimeLine::setYLabels( QStringList labellist )
    {
    m_ylabellist.clear();
    m_ylabellist = labellist;
    }

    void CRealTimeLine::setDrawStartLeft( bool startleft /= true/ )
    {
    m_isstartleft = startleft;
    }

    void CRealTimeLine::addDataList( QList dlist )
    {
    for (int i = 0 ; i < dlist.count(); ++i)
    {
    addDataList(dlist.at(i));
    }
    }

    void CRealTimeLine::addDataList( float value )
    {
    int tmp = (int)value+1;
    if (tmp > m_ymax)
    {
    m_ymax = tmp*1.2;
    }

    m_ymin = qMin(m_ymin,tmp);
    if (m_isstartleft)
    {
        m_datelist.append(value);
        if (m_datelist.count() > m_count)
            m_datelist.removeFirst();
    }
    else
    {
        m_datelist.prepend(value);
    
        if (m_datelist.count() > m_count)
            m_datelist.removeLast();
    }
    

    }

    void CRealTimeLine::setMaxValue( int max )
    {
    m_ymax = max;
    }

    void CRealTimeLine::removeDatas()
    {
    m_datelist.clear();
    }

    void CRealTimeLine::setLineColor( QColor color )
    {
    m_linecolor = color;
    }

    void CRealTimeLine::setBackColor( QLinearGradient linegradent )
    {
    m_backlinegradent = linegradent;
    m_backlinegradent.setStart(QPointF(width()/2,0));
    m_backlinegradent.setFinalStop(QPointF(width()/2,height()));
    }

    void CRealTimeLine::setPrefixText( QString text )
    {
    m_textstr = text;
    }

    void CRealTimeLine::setInterval( int interval )
    {
    m_interval = interval;
    }

    void CRealTimeLine::initdata()
    {
    m_originpoint.setX(width()*0.1);
    m_originpoint.setY(height()*0.9);
    m_griddingcount_x = 20;
    m_griddingcount_y = 10;

    m_xlabellist.clear();
    QDateTime curtime = QDateTime::currentDateTime();
    int setp = QDateTime::currentDateTime().toTime_t()-m_olddateime.toTime_t();
    
    if (setp > m_count )
    {
        m_olddateime = m_olddateime.addSecs(m_interval);
    }
    if (m_isstartleft)
    {
        QTime ctime = m_olddateime.time();
        for (int i = 0; i < 5; ++i)
        {
            QTime tmp = ctime.addSecs(i*6*60); //30分钟
            m_xlabellist.append(tmp.toString("hh:mm:ss"));
        }
    }
    else
    {
        QTime ctime = QDateTime::currentDateTime().time();
        for (int i = 0; i < 5; ++i)
        {
            QTime tmp = ctime.addSecs(-i*6*60); //30分钟
            m_xlabellist.push_front(tmp.toString("hh:mm:ss"));
        }
    }
    
    m_ylabellist.clear();
    float step = 1.0*(m_ymax - m_ymin)/10;
    for (int i = 0; i < 11; ++i)
    {
        m_ylabellist << QString("%1").arg(m_ymin + step*i);
    }
    

    }

    void CRealTimeLine::paintEvent( QPaintEvent * event )
    {
    initdata();

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::TextAntialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    QFont font;
    font.setPixelSize(11);
    painter.setFont(font);
    
    painter.save();
    painter.setPen(QPen(Qt::lightGray));
    painter.setBrush(m_backlinegradent);
    painter.drawPath(drawBack(painter));
    painter.restore();
    
    drawText(painter);
    
    painter.save();
    //painter.setBrush(m_backlinegradent);
    painter.drawPath(drawRectPath());
    painter.restore();
    
    painter.save();
    QPen pen;
    pen.setColor(Qt::lightGray);
    pen.setStyle(Qt::DotLine);
    painter.setPen(pen);
    painter.drawPath(drawGridding());
    painter.restore();
    
    
    painter.drawPath(drawXYScalePath());
    drawXLabel(painter);
    drawYLabel(painter);
    
    drawLine(painter);
    

    }

    QPainterPath CRealTimeLine::drawGridding()
    {
    //QPainter painter(this);
    QPointF oldp(m_originpoint);
    //画背景虚线
    QPainterPath gridding_xypath;
    oldp = m_originpoint;

    int w = width()*0.8;
    int h = height()*0.8;
    float index = 1.0*w/m_griddingcount_x;
    for (int i = 0; i < m_griddingcount_x; ++i)
    {
        oldp.setX(oldp.x()+index);
        gridding_xypath.moveTo(oldp);
        gridding_xypath.lineTo(oldp.x(),oldp.y()-h);
    }
    
    oldp = m_originpoint;
    index = 1.0*h/m_griddingcount_y;
    for (int i = 0; i < m_griddingcount_y; ++i)
    {
        oldp.setY(oldp.y() - index);
        gridding_xypath.moveTo(oldp);
        gridding_xypath.lineTo(oldp.x()+w,oldp.y());
    }
    
    return gridding_xypath;
    

    }

    QPainterPath CRealTimeLine::drawRectPath()
    {
    int w = width()*0.8;
    int h = height()*0.8;
    QPainterPath XYPathRect;
    XYPathRect.addRect(m_originpoint.x(),m_originpoint.y()-h,w,h);
    return XYPathRect;
    }

    QPainterPath CRealTimeLine::drawBack( QPainter &painter )
    {
    QPainterPath XYPathRect;
    XYPathRect.addRect(0,0,width(),height());
    return XYPathRect;
    }

    QPainterPath CRealTimeLine::drawXYScalePath()
    {
    int w = width()*0.8;
    int h = height()*0.8;
    QPainterPath XYPath;
    //画刻度X
    QPointF oldp(m_originpoint);

    float index = 1.0*w/m_griddingcount_x;
    int tickcount = 5;
    for (int i = 0; i < m_griddingcount_x; ++i)
    {
        QPointF tmppoint(oldp);
        float index_tmp = index/tickcount;
    
        tmppoint.setX(tmppoint.x()+index*i);
        for (int j = 0 ; j < tickcount ;j++)
        {
            QPointF p(tmppoint);
            int d = 0;
            if (j == 0)
                d = 2;
    
            p.setX(p.x()+index_tmp*j);
            XYPath.moveTo(p);
            p.setY(p.y() + 5+d);
    
            XYPath.lineTo(p);
        }
    }
    
    //画刻度Y
    index = 1.0*h/m_griddingcount_y;
    tickcount = 1;
    for (int i = 0; i < m_griddingcount_y; ++i)
    {
        QPointF tmppoint(oldp);
        float index_tmp = index/tickcount;
        tmppoint.setY(tmppoint.y()-index*i);
        for (int j = 0 ; j < tickcount ;j++)
        {
            QPointF p(tmppoint);
            int d = 0;
            if (j == 0)
                d = 2;
            p.setY(p.y() - index_tmp*j);
            XYPath.moveTo(p);
            p.setX(p.x() - 5-d);
            XYPath.lineTo(p);
            //p.setX(p.x() + 5);
        }
    }
    
    //if (m_y2_visable)
    //{
    //  oldp =m_originpoint;
    //  oldp.setX(oldp.x()+m_length_x);
    //  for (int i = 0; i < m_tickcount_y2; ++i)
    //  {
    //      QPointF p(oldp);
    //      p.setY(p.y() - m_tick_y2_index*i);
    //      XYPath.moveTo(p);
    //      p.setX(p.x() + m_tick_xy);
    
    //      XYPath.lineTo(p);
    
    //  }
    //}
    
    return XYPath;
    

    }

    void CRealTimeLine::drawXLabel(QPainter &painter)
    {
    painter.save();
    //画X
    if (m_xlabellist.isEmpty() ) return;
    int w = width()*0.8;
    //int h = height()*0.8;

    QPointF oldp(m_originpoint);
    int _height = 15;
    int index = w/(m_xlabellist.count()-1);
    for (int i = 0; i < m_xlabellist.count(); ++i)
    {
        QString textstr = m_xlabellist.at(i);
        QPointF p(oldp);
        p.setY(p.y()+5);
    
        float x = p.x()+index*i-10;
        float y = p.y();
    
        QRectF rect_(x,y,textstr.length()*10,_height);
        painter.drawText(rect_, Qt::AlignTop, textstr);
    
    }
    painter.restore();
    

    }

    void CRealTimeLine::drawYLabel(QPainter &painter)
    {
    if (m_ylabellist.isEmpty() ) return;
    //int w = width()*0.8;
    int h = height()*0.8;

    //画Y
    QPointF oldp(m_originpoint);
    int _height = 15;
    int index = h/(m_ylabellist.count()-1);
    for (int i = 0; i < m_ylabellist.count(); ++i)
    {
        QString textstr = m_ylabellist.at(i);
        QPointF p(oldp);
    
        float x = p.x()-_height*textstr.length()-10;
        float y = p.y()-index*i-10;
    
        QRectF rect_(x,y,_height*textstr.length(),20);
    
        painter.drawText(rect_, Qt::AlignRight, textstr);
    }
    painter.restore();
    

    }

    void CRealTimeLine::drawText( QPainter &painter )
    {
    painter.save();
    QFont font;
    font.setPixelSize(12);
    painter.setFont(font);
    int w = width()*0.1;
    int h = height()*0.02;
    QString str;
    if (m_isstartleft)
    {
    if (m_datelist.count() > 0)
    {
    QString tstr = QString::number(m_datelist.last(),’f’,2);
    str = QString(“%1%2”).arg(m_textstr).arg(tstr);
    }
    else
    str = m_textstr;
    }
    else
    {

        if (m_datelist.count() > 0)
        {
            QString tstr = QString::number(m_datelist.first(),'f',2);
            str = QString("%1%2").arg(m_textstr).arg(tstr);
        }
        else
            str = m_textstr;
    }
    QRectF rect(w,h,w*8,h*4);
    painter.drawText(rect, Qt::AlignLeft, str);
    painter.restore();
    

    }

    void CRealTimeLine::drawLine(QPainter &painter)
    {

    painter.save();
    QColor color = m_linecolor;
    if (m_isstartleft)  //左侧开始
    {
        painter.setPen(QPen(color));
        painter.drawPath(drawLineLeftPath());
    }
    else
    {
        painter.setPen(QPen(color));
        painter.drawPath(drawLineRigthPath());
    }
    painter.restore();
    

    }

    QPainterPath CRealTimeLine::drawLineLeftPath()
    {
    QPainterPath linepath;
    int w = width()*0.8;
    int h = height()*0.8;
    QPointF oldp(m_originpoint);
    float step = 1.0*w/m_count;
    float ystep = 1.0*h/(m_ymax-m_ymin);
    if (m_datelist.isEmpty()) return linepath;
    if (m_datelist.count() == 1)
    {
    linepath.moveTo(m_originpoint.x(),m_originpoint.y() - ystep*m_datelist.at(0));
    linepath.lineTo(m_originpoint.x()+5,m_originpoint.y() -ystep*m_datelist.at(0));
    return linepath;
    }
    for (int i = 0 ; i < m_datelist.count()-1; ++i)
    {
    linepath.moveTo(m_originpoint.x()+step*i,m_originpoint.y() - ystep*m_datelist.at(i));
    linepath.lineTo(m_originpoint.x()+step*i+step,m_originpoint.y() -ystep*m_datelist.at(i+1));
    }
    return linepath;
    }

    QPainterPath CRealTimeLine::drawLineRigthPath()
    {
    QPainterPath linepath;
    float w = width()*0.8;
    int h = height()*0.8;

    float step = 1.0*w/m_count;
    float ystep = 1.0*h/(m_ymax-m_ymin);
    if (m_datelist.isEmpty()) return linepath;
    if (m_datelist.count() == 1)
    {
        linepath.moveTo(m_originpoint.x()+w,m_originpoint.y() - ystep*m_datelist.at(0));
        linepath.lineTo(m_originpoint.x()+w-5,m_originpoint.y() -ystep*m_datelist.at(0));
        return linepath;
    }
    //QPointF oldp(m_originpoint);
    //oldp.setX(m_originpoint.x()+w-step*m_datelist.count());
    for (int i = m_datelist.count()-1 ; i > 0; --i)
    {
        linepath.moveTo(m_originpoint.x()+w-step*i,m_originpoint.y() - ystep*m_datelist.at(i));
        linepath.lineTo(m_originpoint.x()+w-step*i+step,m_originpoint.y() -ystep*m_datelist.at(i-1));   
    }
    
    
    return linepath;
    

    }

    “`

    展开全文
  • Qt绘制实时曲线图形简单例程 - Qt实时绘图

    万次阅读 多人点赞 2018-10-16 11:30:36
    本来是想写一篇上位机通过串口接收数据并进行简单实时动态画图的,但是网上关于Qt串口接收数据的博客已经非常多了,... 使用Qt绘制图形,首先需要了解Qt的窗口与视口的概念,理解Qt的坐标变换,然后学会掌握Qpaint...

           本来是想写一篇上位机通过串口接收数据并进行简单实时动态画图的,但是网上关于Qt串口接收数据的博客已经非常多了,且也会导致内容太多,显得复杂,如果需要串口收发数据例程,网上随便百度就能收到了,也可以下载我写的北斗/GPS双模定位上位机,这里主要介绍一下收到数据后的画图实现。
           使用Qt绘制图形,首先需要了解Qt的窗口与视口的概念,理解Qt的坐标变换,然后学会掌握Qpainter这个类的使用就能实现基本的绘图功能了。下面一个实时绘制曲线图形的例子(坐标用应该直接使用一个Qpoint模板的列表表示比较好)。这里,实时数据只是由使用creatData函数产生,在实际工程中将数据改为读取实时数据即可。

    头文件

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QTimer>
    #include <QList>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    protected:
        void paintEvent(QPaintEvent *);
    public:
        int m_count;
        float x;
        QTimer* m_Timer;
        QList<float> xList;
        QList<float> yList;
    
        Widget(QWidget *parent = 0);
        ~Widget();
    
    public slots:
        void creatData();
    
    };
    
    #endif // WIDGET_H

    源文件

    #include "Widget.h"
    #include <QPainter>
    #include <QPointF>
    #include <QPen>
    #include <qmath.h>
    Widget::Widget(QWidget *parent) : QWidget(parent)
    {
        x = -10;
        m_count = 0;
        m_Timer = new QTimer(this);
        m_Timer->start(10);
        connect(m_Timer,SIGNAL(timeout()),this,SLOT(creatData()));
    }
    void Widget::creatData()
    {
        x += 0.2;
        m_count += 1;
        if(m_count%2)
        {
            xList.append(x);
            yList.append(qSin(x));
        }
        else
        {
            xList.append(x);
            yList.append(qSin(x));
            update();
        }
        if(m_count == 100)
        {
            xList.clear();
            yList.clear();
            m_count = 0;
            x = -10;
        }
    }
    void Widget::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        QPen pen;
        pen.setColor(Qt::green);
        pen.setStyle(Qt::SolidLine);
        pen.setWidthF(0.05);
        painter.setPen(pen);
        painter.setViewport(50, 50, width()-100, height()-100);
        painter.setWindow(-10, 2, 20, -4); // (-10, 2)    (10, -2)
        painter.fillRect(-10, 2, 20, -4, Qt::white);
        painter.drawLine(QPointF(-10, 0), QPointF(10, 0));   // x
        painter.drawLine(QPointF(0, 2), QPointF(0, -2));     // y
        for(int i = 0; i < yList.count(); i++)
        {
            if(i == 0)
                painter.drawPoint(QPointF(xList[i], yList[i]));
            else
                painter.drawLine(QPointF(xList[i-1], yList[i-1]), QPointF(xList[i], yList[i]));
        }
    }
    Widget::~Widget()
    {
        
    }

    主函数

    #include <QApplication>
    #include "Widget.h"
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
        
        return a.exec();
    }
    展开全文
  • Qt- 绘制实时曲线

    千次阅读 2014-08-13 23:53:04
    功能描述:用曲线来显示数据的变化情况。横坐标表示时间T,纵坐标Y。每隔一定时间取一个Y值确定纵坐标 点击(此处)折叠或打开 #include "dialog.h" #include "ui_dialog.h" Dialog::...
  • QT qwt绘制实时动态曲线demo

    千次阅读 2018-11-13 21:28:35
    qwt插件是一个绘图插件,提供了非常强大的常用的ui控件,这里我需要用到该插件在树莓派3B+绘制一个实时动态的曲线,用于绘制当前采集器的温湿度环境曲线。 关于如何在树莓派上安装qwt的教程,请参考我前面写的博文...
  • 使用QT绘制温度曲线

    千次阅读 2019-05-17 15:59:29
    直接使用QT5.7.0做温度曲线,这样就不用安装qtcharts了 参考链接:https://blog.csdn.net/czyt1988/article/details/51399341
  • QT5使用QCustomPlot绘制实时曲线

    万次阅读 2016-08-05 18:14:35
    而用QT绘制漂亮的实时曲线,通常有两种方法,一是QWT控件,二是QCustomPlot控件。由于QWT安装相当繁琐,于是笔者使用了QCustomPlot。一、下载、解压QCustomPlot源码QCustomPlot下载1、下载完整版并解压,将文件夹...
  • Qt绘制贝塞尔曲线

    千次阅读 2013-09-25 09:17:53
    绘制一个曲线,网上找了一堆,都是不知所云的,要么画定点的曲线、要么就copy一个画贝塞尔曲线的公式然后一堆XXXX的那些。 好像弄Qt搞的很少,网上都找不到这样的……汗~ 下面是本人折腾的东西,一些代码片段,...
  • Qt绘制动态曲线

    2020-05-13 17:45:55
    * 绘制鼠标跟随 */ void CustomCurceMaster::drawLine(QPainter *painter) { painter->save(); //painter->setPen(QColor("#FFFFFF")); painter->setBrush(QBrush(QColor("#E33E33"))); .
  • Qt使用QCustomPlot绘制实时曲线 代码 核心代码https://gitee.com/ALONE_WORK/codes/6ck3m1zornbptai2sgxju22 截图演示
  • Qt绘制动态曲线

    2020-08-08 17:41:36
    #ifndef QLINEWIDGET_H #define QLINEWIDGET_H #include <QWidget> #include <QtCharts/QChart> #include <QtCharts/QChartView>...QtCharts/QPieSeries>...QtCharts/QAbstractBarSeries>
  • Qt绘制贝塞尔曲线例程

    千次阅读 2016-08-29 10:31:45
    main.cpp [cpp] view plain copy #include  #include "mywidget.h"    int main(int argc, char *argv[])  {   QApplication a(argc, argv);  ... 
  • 使用QT动态绘制动态曲线,亲自调试成功 支持最新QT版本QT5.0 实时绘制,实时显示,生产随机数,绘制波形 (Use QT dynamic mapping dynamic curve, personally successful commissioning Support for the latest version...
  • 2.使用这个类不需要添加dll操作,只需把“qcustomplot.h”和“qcustomplot.cpp”两个文件复制到工程目录下。 3.界面设计时拖一个Widget到画图区域,对这个控件->右键“提升为”->QCustomPlot。...
  • qt绘制曲线

    2020-07-30 23:31:51
    qt中绘制过指定点集的曲线 功能:1.过指定点集 2.绘制曲线 可能问题:曲线不够平滑
  • Qt绘制曲线

    千次阅读 2016-08-19 08:43:03
    Qt的图形界面很厉害,之前的项目中用到的都是Qt的一些简单的应用,通过绘制曲线才对Qt的图形有了初步的了解。原来我也可以画出美丽平滑的余弦曲线。 1 坐标转换 (1)坐标系的认识 在绘制曲线之前,先要...
1 2 3 4 5 ... 20
收藏数 3,335
精华内容 1,334
关键字:

qt绘制实时曲线