删除文章

确定要删除这篇文章吗?

取消
确定

QtCharts使用

     阅读(84)  2020-09-03 01:39:09

QtCharts是Qt的图表模块在Qt5.7版本之后才包含进来的,之前的版本需要下载源码单独编译。

介绍几个重要的类:
QChart:Qt图标的核心类,建立在图形视图之上的,管理各个图表部件
QChartView:是一个独立的widget用来展示QChart
QDateTimeAxis:日期时间轴
QValueAxis:数值轴
QLineSeries:折线图
QScatterSeries:离散图

demo截图:
qcharts_demo

源码:
MyChart.h

#pragma once
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QPen>
using namespace QtCharts;

class QMouseEvent;
class QLabel;
class QTimer;
class QGraphicsLineItem;
class MyChart : public QChartView
{
    Q_OBJECT

public:
    MyChart(QWidget *parent = nullptr);
    ~MyChart();
    void init();
    void updateXList();

protected:
    virtual void showEvent(QShowEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void resizeEvent(QResizeEvent *event);

private:
    QTimer *m_timer;
    QLabel *m_showLabel;
    QGraphicsLineItem *m_lineItem;
    QList<QPointF> m_xList;
    QPen m_middleLinePen;
    QPoint m_middlePos;
};

MyChart.cpp

#include "MyChart.h"
#include <QEvent>
#include <QtCharts/QLineSeries>
#include <QtCharts/qxyseries.h>
#include <QtCore/QRandomGenerator>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QValueAxis>
#include <QtCharts/QDateTimeAxis>
#include <QtCharts/QScatterSeries>
#include <QTime>
#include <QTimer>
#include <QDateTime>
#include <QLabel>
#include <QDebug>

typedef QPair<qint64, int> Data;
typedef QList<Data> DataList;
typedef QList<DataList> DataTable;

const int g_listCount = 2;
DataTable g_dataTable;

int getRandom(int maxValue)
{
    return QRandomGenerator::global()->bounded(maxValue);
}

DataTable generateRandomData(int listCount, int &maxX, int &maxY)
{
    DataTable dataTable;

    // generate random data
    for (int i(0); i < listCount; i++) {
        QDateTime start = QDateTime(QDateTime::currentDateTime().date(), QTime(8, 0));

        DataList dataList;
        int yValue(0);
        int xIndex = 0;
        for (int j(0); j < 11; j++) {
            yValue = yValue + getRandom(100);
            maxY = yValue;
            maxX = xIndex++;

            dataList << Data(start.toMSecsSinceEpoch(), yValue);
            start = start.addSecs(3000);
        }
        dataTable << dataList;
    }

    return dataTable;
}

MyChart::MyChart(QWidget *parent)
    : QChartView(parent), m_lineItem(nullptr)
{
    init();
}

MyChart::~MyChart()
{
}


void MyChart::init()
{
    m_middleLinePen.setStyle(Qt::DashLine);
    m_middleLinePen.setColor(Qt::red);

    m_timer = new QTimer(this);
    m_timer->setSingleShot(true);
    m_timer->setInterval(10);

    m_showLabel = new QLabel(this);
    m_showLabel->hide();
    m_showLabel->setFixedSize(120, 60);
    m_showLabel->setWindowFlag(Qt::ToolTip);
    m_showLabel->setFocusPolicy(Qt::NoFocus);

    int g_xMax = 0;
    int g_yMax = 0;
    g_dataTable = generateRandomData(g_listCount, g_xMax, g_yMax);

    QDateTimeAxis *axisX = new QDateTimeAxis(); // X轴是时间
    axisX->setFormat("HH:mm");
    axisX->setTickCount(11);
    QDateTime start = QDateTime(QDateTime::currentDateTime().date(), QTime(8, 0));
    QDateTime end = QDateTime(QDateTime::currentDateTime().date(), QTime(18, 0));
    axisX->setRange(start, end);

    QValueAxis *axisY = new QValueAxis(); // Y轴是值
    axisY->setRange(0, g_yMax * 1.5);
    axisY->setLabelFormat("%i");
    axisY->setTickCount(6);

    QChart *chart = new QChart();
    chart->setTitle("Line chart");
    chart->addAxis(axisX, Qt::AlignBottom);
    chart->addAxis(axisY, Qt::AlignLeft);
    this->setChart(chart);

    QString name("Series ");
    int nameIndex = 0;
    for (const DataList &list : g_dataTable) {
        QLineSeries *lineSeries = new QLineSeries(); // 线图
        QScatterSeries *scatterSeries = new QScatterSeries(); // 离散图
        scatterSeries->setMarkerShape(QScatterSeries::MarkerShapeCircle);//圆形的点
        scatterSeries->setBorderColor(QColor(21, 100, 255)); //离散点边框颜色
        scatterSeries->setBrush(QBrush(QColor(21, 100, 255)));//离散点背景色
        scatterSeries->setMarkerSize(6); //离散点大小

        for (const Data &data : list) {
            QPointF pp((qreal)data.first, (qreal)data.second);
            lineSeries->append(pp);
            scatterSeries->append(pp);
        }

        lineSeries->setName(name + QString::number(nameIndex));
        nameIndex++;
        chart->addSeries(lineSeries);
        chart->addSeries(scatterSeries);
        chart->legend()->hide(); // 图标标题

        lineSeries->attachAxis(axisY);
        lineSeries->attachAxis(axisX);
        scatterSeries->attachAxis(axisY);
        scatterSeries->attachAxis(axisX);
    }

    this->setRenderHint(QPainter::Antialiasing, true);
    this->setMouseTracking(true);
}

void MyChart::updateXList()
{
    m_xList.clear();
    if (!g_dataTable.isEmpty()) {
        for (int i = 0; i < g_dataTable[0].size(); i++) {
            Data d = g_dataTable[0][i];
            QPointF p = this->chart()->mapToPosition(QPointF(d.first, d.second));
            m_xList << p;
        }
    }
}

void MyChart::showEvent(QShowEvent *event)
{
    updateXList();
    QChartView::showEvent(event);
}

void MyChart::resizeEvent(QResizeEvent *event)
{
    updateXList();
    QChartView::resizeEvent(event);
}

void MyChart::mouseMoveEvent(QMouseEvent *event)
{
    QPoint p = event->pos();
    if (this->chart()->plotArea().contains(p)) {
        QPointF pf;
        int lastDiff = -1;
        foreach(const QPointF &px, m_xList) {
            int diff = qAbs((int)px.x() - p.x());
            if (lastDiff < 0) {
                lastDiff = diff;
                pf = px;
            }
            else {
                if (diff < lastDiff) {
                    lastDiff = diff;
                    pf = px;
                }
            }
        }
        QPoint pf2((int)pf.x(), (int)pf.y());
        if (m_middlePos != pf2) {
            m_middlePos = pf2;
            QPointF pv = this->chart()->mapToValue(pf);
            QRectF r = this->chart()->plotArea();
            QGraphicsLineItem *oldItem = m_lineItem;
            m_lineItem = this->scene()->addLine(QLine(QPoint(m_middlePos.x(), (int)r.y()), QPoint(m_middlePos.x(), (int)(r.y() + r.height()))), m_middleLinePen);
            if (oldItem) {
                this->scene()->removeItem(oldItem);
            }
            QStringList ls;
            ls << "xxx title";
            ls << "time:" + QDateTime::fromMSecsSinceEpoch((qint64)pv.x()).toString("HH:mm");
            ls << "deal:" + QString::number(pv.y());
            m_showLabel->setText(ls.join("\n"));
        }

        QPoint labelPos = this->mapToGlobal(p);
        labelPos.setX(labelPos.x() + 20);
        labelPos.setY(labelPos.y() + 10);
        m_showLabel->move(labelPos);
        m_showLabel->show();
    }
    else {
        m_showLabel->hide();
        if (m_lineItem) {
            this->scene()->removeItem(m_lineItem);
        }
    }
    QChartView::mouseMoveEvent(event);
}

文章评论

Keep it simple,stupid
文章数
347
今日访问
1151
今日IP数
503
最近评论

在家赚钱: 在家赚钱 <a href="http://www.265250.com/" >在家赚钱</a> 已阅,感谢站长分享!
liangzi: 不错 谢谢分享
tujiaw: registerThreadInactive:如果当前没有激活的线程,就去激活线程,让等待的线程去执行任务。
hgzzx: 佩服佩服。 请教:registerThreadInactive的作用是什么?
xuehaoyun: 很不错,来围观一下
tujiaw: 抱歉csdn code服务关闭了,这个代码我也找不到了
回到顶部