QtCharts的简单用法(2)--Qt

前言

很多时候,我们用QtCharts不仅仅只是显示个线条趋势什么的,还需要一些小的功能,比如只显示某条线条,再比如让动态的线条停止滚动等。所以这篇博客就是介绍的这些东西,碎而杂。

简述

本文主要介绍如下几个功能:

(1)静态模式(数据依旧接收,但线条静止;当退出当前模式,线条动态,并将之前的数据刷上去)

(2)横坐标为日期时间,如2018-06-25 14:35:45:000

(3)浮标的显示(跟示波器相似)

 

示例

(1)静态模式:只要将接收到的数据缓存下(即找个容器存放下),退出此模式再刷上去就可以了。下面的代码有考虑上下限,可能有些地方不太完善。

private:
    Ui::MainWindow *ui;

    QChart *m_chart;
    QDateTimeAxis* m_axisX;
    QValueAxis* m_axisY;
    QLineSeries* m_series;
    QTimer m_timer;
    QDateTime m_maxDateTime;    //横轴时间最大值
    QGraphicsLineItem* m_upperLineItem;
    QGraphicsLineItem* m_lowerLineItem;

    bool staticModelFlag;      //静态模式biaoshi标识
    QList m_points;  //装静态时产生的数据
    int m_seriesMaxSize;      //series的数据容量

 

void MainWindow::handleTimeout()
{
    qreal y=qrand() % 50;   //随机产生的数值
    QDateTime currentDateTime=QDateTime::currentDateTime();

    QPointF point(QDateTime::currentDateTime().toMSecsSinceEpoch(),y);


    if(staticModelFlag)
    {//静态模式
        m_points.push_back(point);
    }else{
        //非静态模式
        QList points=m_series->points();

        qreal max=m_axisY->max();

        for(int i=0;imax)
                max=m_points[i].y();
        }

        if(!m_points.isEmpty()){
            points.append(m_points);
            m_points.clear();
        }

        points.append(point);

        //清除多余数据
        while(points.size()>m_seriesMaxSize)
        {
            points.pop_front();
        }

        m_series->replace(points);

        //重置x轴范围
        if(currentDateTime>m_axisX->max())
        {
            QDateTime max=m_axisX->max();
            if(max.toTime_t()==0)
            {
                m_maxDateTime=currentDateTime.addSecs(60);
                m_axisX->setRange(currentDateTime,m_maxDateTime);
            }else{
                m_maxDateTime=currentDateTime;
                m_axisX->setRange(m_maxDateTime.addSecs(-60),m_maxDateTime);
            }


        }

        //重置y轴范围
        m_axisY->setMax(qMax(max,y));
    }

}

(2)横坐标为日期时间。这个功能很简单,修改下横轴就可以:将横轴从QValueAxis修改成QDateTimeAxis。

    m_axisX=new QDateTimeAxis;
    m_axisX->setTickCount(4);
    m_axisX->setFormat("yyyy-MM-dd hh:mm:ss:zzz"); //设置格式

    m_chart->addAxis(m_axisX, Qt::AlignBottom);
    m_series->attachAxis(m_axisX);

    m_axisY=new QValueAxis;
    m_axisY->setTickCount(11);
    m_axisY->setRange(0,40);
    m_axisY->setLabelFormat("%i");
    m_chart->addAxis(m_axisY,Qt::AlignLeft);
    m_series->attachAxis(m_axisY);

下面给出以上两个小功能,结合在一起的界面效果。

QtCharts的简单用法(2)--Qt_第1张图片

(3)浮标的显示。这个功能我参考了Qt自带的示例Callout。这个部分将QChart与图像框架部分结合了起来。用到了类QGraphicsItem,QGraphicsLineItem,QGraphicsScene等。

浮标代码:

#ifndef CALLOUT_H
#define CALLOUT_H

#include 
#include 
#include 
#include

QT_CHARTS_USE_NAMESPACE

class CallOut : public QGraphicsItem
{
public:
    CallOut(QChart *parent);

    void setText(const QString &text);
    void setAnchor(QPointF point);
    void updateGeometry();

    QRectF boundingRect() const;

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);

private:
    QString m_text;
    QRectF m_textRect;
    QRectF m_rect;
    QPointF m_anchor;
    QFont m_font;
    QChart *m_chart;


};

#endif // CALLOUT_H
#include "callout.h"

#include 

CallOut::CallOut(QChart *chart):
    QGraphicsItem(chart),
    m_chart(chart)
{

}

void CallOut::setText(const QString &text)
{
    m_text=text;

    QFontMetrics metrics(m_chart->font());
    m_textRect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt::AlignLeft, m_text);
    m_textRect.translate(5, 5);
    prepareGeometryChange();
    m_rect = m_textRect.adjusted(-5, -5, 5, 5);

}

void CallOut::setAnchor(QPointF point)
{
    m_anchor=point;
}

void CallOut::updateGeometry()
{
    prepareGeometryChange();
    QPointF anchor;
    anchor.setX(-m_rect.width()/2+m_anchor.x());
    anchor.setY(m_chart->plotArea().height()/2);
    setPos(anchor);
}

QRectF CallOut::boundingRect() const
{
    QPointF anchor = mapFromParent(m_anchor);
    QRectF rect;
    rect.setLeft(qMin(m_rect.left(), anchor.x()));
    rect.setRight(qMax(m_rect.right(), anchor.x()));
    rect.setTop(qMin(m_rect.top(), anchor.y()));
    rect.setBottom(qMax(m_rect.bottom(), anchor.y()));
    return rect;
}

void CallOut::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option)
    Q_UNUSED(widget)
    QPainterPath path;
    path.addRoundedRect(m_rect,5,5);

    //path=path.simplified();

    painter->setBrush(QColor(93,93,93,90));
    painter->setPen(QPen(QColor(93,93,93,75)));
    painter->drawPath(path);
    painter->setPen(QPen(Qt::white));
    painter->drawText(m_textRect,m_text);


}

视图:

#ifndef CHARTVIEW_H
#define CHARTVIEW_H

#include
#include
#include
#include
#include
#include 
#include 
#include 
#include 
#include
#include"callout.h"
#include"chart.h"


QT_CHARTS_USE_NAMESPACE

class ChartView : public QChartView
{
    Q_OBJECT
public:
    ChartView(QWidget *parent = 0);

    qreal getYValue(QPointF p1,QPointF p2,qreal x);


protected:

    bool viewportEvent(QEvent *event)override;
    void mousePressEvent(QMouseEvent *event)override;
    void mouseMoveEvent(QMouseEvent *event)override;
    void mouseReleaseEvent(QMouseEvent *event)override;



public slots:
    void connectMarkers();
    void handleMarkerClicked();


private:
    QGraphicsLineItem* m_LineItem;
    QGraphicsLineItem* m_topLineItem; //上限
    QGraphicsLineItem* m_lowLineItem; //下限
    CallOut* m_tooltip;
    Chart *m_chart ;
    bool m_isTouching;

public:
    bool m_isBuoyShow;

};

#endif // CHARTVIEW_H
#include "chartview.h"
#include
#include
#include 
#include 
#include 
#include
#include

#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif

ChartView::ChartView(QWidget *parent) :
    QChartView(parent),
    m_tooltip(0),
    m_isTouching(false),
    m_isBuoyShow(false),
    m_topLineItem(0),
    m_lowLineItem(0)
{

    m_chart=new Chart;


    QLineSeries *series = new QLineSeries;
    series->append(1, 3);
    series->append(4, 5);
    series->append(5, 4.5);
    series->append(7, 1);
    series->append(11, 2);
    series->setName("参数一");
    m_chart->addSeries(series);

    QSplineSeries *series2 = new QSplineSeries;
    series2->append(1.6, 1.4);
    series2->append(2.4, 3.5);
    series2->append(3.7, 2.5);
    series2->append(7, 4);
    series2->append(10, 2);
    series2->setName("参数二");
    m_chart->addSeries(series2);

    m_chart->setTitle("Zoom in/out example");
    //m_chart->setAnimationOptions(QChart::SeriesAnimations);
    //m_chart->legend()->setAlignment(Qt::AlignRight);
    m_chart->createDefaultAxes();

    this->setChart(m_chart);

    m_LineItem = new QGraphicsLineItem();

    QPen pen=m_LineItem->pen();
    pen.setColor(QColor(93,93,93,75));
    pen.setWidth(3);
    m_LineItem->setPen(pen);

    this->scene()->addItem(m_LineItem);
    m_LineItem->hide();

    connectMarkers();

    this->setRubberBand(QChartView::RectangleRubberBand);


}

qreal ChartView::getYValue(QPointF p1, QPointF p2, qreal x)
{
    qreal y=(p2.y()-p1.y())/(p2.x()-p1.x())*(x-p1.x())+p1.y();
    return y;

}

bool ChartView::viewportEvent(QEvent *event)
{
    if (event->type() == QEvent::TouchBegin) {

        m_isTouching = true;

        chart()->setAnimationOptions(QChart::NoAnimation);
    }
    return QChartView::viewportEvent(event);
}

void ChartView::mousePressEvent(QMouseEvent *event)
{
    if (m_isTouching)
        return;
    QChartView::mousePressEvent(event);
}

void ChartView::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isTouching)
        return;

    QChartView::mouseMoveEvent(event);

    if(m_isBuoyShow){
        bool flag=m_chart->plotArea().contains(event->pos());
        if(flag)
        {//在坐标轴中

            if (m_tooltip == 0)
                m_tooltip = new CallOut(m_chart);

            qreal pointX=m_chart->mapToValue(event->pos()).x();

            QList seriesList=m_chart->series();
            QString text="";
            for(int i=0;i points=series->points();
               for(int j=0;jpointX)
                   {
                       if(j-1>=0){
                           qreal pointY=getYValue(curPoint, points[j-1],pointX);
                           QPointF point(pointX,pointY);
                           text+=tr("X%1:%2 Y%1:%4 \n").arg(i).arg(point.x()).arg(point.y());
                       }
                       break;
                   }
               }

            }
             m_tooltip->setText(text);
             m_tooltip->setAnchor(event->pos());
             m_tooltip->setZValue(11);
             m_tooltip->updateGeometry();
             m_tooltip->show();

             m_LineItem->setLine(QLineF(event->pos().x(),0,event->pos().x(),this->rect().height()));
             m_LineItem->show();

        }else{
            if(m_tooltip!=0)
                m_tooltip->hide();
            m_LineItem->hide();
        }
    }

}

void ChartView::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_isTouching)
        m_isTouching = false;

    // Because we disabled animations when touch event was detected
    // we must put them back on.
    chart()->setAnimationOptions(QChart::SeriesAnimations);

    QChartView::mouseReleaseEvent(event);
}



void ChartView::connectMarkers()
{
    foreach (QLegendMarker* marker, m_chart->legend()->markers()) {
        QObject::disconnect(marker, SIGNAL(clicked()), this, SLOT(handleMarkerClicked()));
        QObject::connect(marker, SIGNAL(clicked()), this, SLOT(handleMarkerClicked()));
    }

}

void ChartView::handleMarkerClicked()
{

    QLegendMarker* marker = qobject_cast (sender());
    Q_ASSERT(marker);

    switch (marker->type())

    {
        case QLegendMarker::LegendMarkerTypeXY:
        {

        marker->setVisible(true);

        qreal alpha;

        QColor color;
        QPen pen = marker->pen();
        color = pen.color();

        if(color.alphaF()==1.0){
            //未点击
            alpha=0.2;

            QFont font=marker->font();
            font.setBold(true);
            marker->setFont(font);

        }else {
            //已点击
            alpha=1.0;

            QFont font=marker->font();
            font.setBold(false);
            marker->setFont(font);
        }

        QList seriesList=m_chart->series();

        for(int i=0;iseries()){
               QPen seriesPen=series->pen();
               QColor color=seriesPen.color();
               color.setAlphaF(alpha);
               seriesPen.setColor(color);
               series->setPen(seriesPen);


           }
        }

        color.setAlphaF(alpha);
        pen.setColor(color);
        marker->setPen(pen);



        break;
        }
    default:
        {
        qDebug() << "Unknown marker type";
        break;
        }
    }


}

界面效果:

QtCharts的简单用法(2)--Qt_第2张图片

结束语

最近没时间上网,这篇写的不是很好,几乎是贴代码。将就,有时间进行调整。

你可能感兴趣的:(Qt,Widgets,QChart,QGraphicsItem,日期轴,浮标)