qChart. model 方式的绘制k线图表更新例子

参考qt自带的barmodelmapper例子

在原有的candlestickchart例子上修改代码,使其通过model来更新candlestickchart,其他图表也是通过这种方式来更新

代码:

MyTableWidget.h文件

#ifndef MYTABLEWIDGET_H
#define MYTABLEWIDGET_H
#include <QtWidgets/QWidget>
#include "customtablemodel.h"
class TableWidget : public QWidget
{
    Q_OBJECT

public:
    TableWidget(QWidget *parent = 0);

private:
    CustomTableModel *m_model;
};

#endif // MYTABLEWIDGET_H

MyTableWidget.cpp

#include "MyTablewidget.h"
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QTableView>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QVXYModelMapper>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QVBarModelMapper>
#include <QtWidgets/QHeaderView>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QCategoryAxis>
#include <QtCharts/QDateTimeAxis>
#include <QtCharts/QValueAxis>
#include <QtCharts/QCandlestickSeries>
#include <QtCore/QDateTime>
#include <QtCharts/QHCandlestickModelMapper>
#include "candlestickdatareader.h"

QT_CHARTS_USE_NAMESPACE

TableWidget::TableWidget(QWidget *parent)
    : QWidget(parent){

    m_model = new CustomTableModel;

    QTableView *tableView = new QTableView;
    tableView->setModel(m_model);
    tableView->setMinimumWidth(400);
   // tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    //tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignHCenter);
    tableView->horizontalHeader()->setHighlightSections(false);
    tableView->horizontalHeader()->setStretchLastSection(true);
    tableView->verticalHeader()->setVisible(false);
    m_model->setParent(tableView);




    QCandlestickSeries *acmeSeries = new QCandlestickSeries();
    //acmeSeries->setBodyOutlineVisible(false);
    QPen p;
    p.setColor(Qt::red);
    acmeSeries->setPen(p);


//    //acmeSeries->setCapsVisible(false);
    acmeSeries->setBodyWidth(0.5);


//    acmeSeries->setName("Acme Ltd");
    acmeSeries->setIncreasingColor(QColor(Qt::red));
    acmeSeries->setDecreasingColor(QColor(Qt::green));

    QChart *chart = new QChart;
    chart->setAnimationOptions(QChart::SeriesAnimations);

    QHCandlestickModelMapper *mapper = new QHCandlestickModelMapper();
    mapper->setOpenColumn(1); //设置open所在表格的哪一列
    mapper->setCloseColumn(4);
    mapper->setHighColumn(2);
    mapper->setLowColumn(3);
    mapper->setFirstSetRow(0);//设置第一条数据在表格的哪一行
    mapper->setLastSetRow(21);
    mapper->setTimestampColumn(0);

    QPen p1;
    mapper->setLastSetRow(22);

    SharesKLineData* tmp = new SharesKLineData();
    tmp->open = 120.0;
    tmp->high = 123.0;
    tmp->close = 119.0;
    tmp->low = 118.80;
    tmp->timestamp = 1438412932000;

    m_model->addData(tmp);
    mapper->setSeries(acmeSeries);
    mapper->setModel(m_model);
    chart->addSeries(acmeSeries);



//    chart->setTitle("Acme Ltd Historical Data (July 2015)");
//    chart->setAnimationOptions(QChart::SeriesAnimations);


    QStringList categories;

    QCategoryAxis *axisX1 = new QCategoryAxis();
    QDateTimeAxis *axisX2 = new QDateTimeAxis();
    QValueAxis *axisX3 = new QValueAxis();

    axisX2->setFormat("yyyy-MM-dd");
    axisX2->setTickCount(5);
    //axisX2->
    //axisX2

    categories << "1" << "2" << "3" << "4" << "5"<<"6"<<"7"<<"8"<<"9"<<"10"<<"11"<<"12"<<"13"<<"14"<<"15"<<"16"<<"17"<<"18"<<"19"<<"20"<<"21"<<"22"<<"23";
    QBarCategoryAxis *axisX = new QBarCategoryAxis();

    axisX->append(categories);


    axisX->setGridLineVisible(false);
    axisX->setLineVisible(true);
    axisX->setLabelsVisible(false);



    chart->addAxis(axisX, Qt::AlignBottom);
    acmeSeries->attachAxis(axisX);
//    chart->addAxis(axisX3,Qt::AlignBottom);
//    acmeSeries->attachAxis(axisX3);



    QValueAxis *axisY = new QValueAxis();
    chart->addAxis(axisY, Qt::AlignRight);
    acmeSeries->attachAxis(axisY);

    chart->legend()->setVisible(false);


//    //! [3]

//    //! [4]
//    chart->createDefaultAxes();

//    QBarCategoryAxis *axisX = qobject_cast<QBarCategoryAxis *>(chart->axes(Qt::Horizontal).at(0));
//    axisX->setCategories(categories);

//    QValueAxis *axisY = qobject_cast<QValueAxis *>(chart->axes(Qt::Vertical).at(0));
//    axisY->setMax(axisY->max() * 1.01);
//    axisY->setMin(axisY->min() * 0.99);
//    //! [4]

//    //! [5]
//    chart->legend()->setVisible(true);
//    chart->legend()->setAlignment(Qt::AlignBottom);
//    //! [5]

//    //! [6]
    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);

//    //! [6]
    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(tableView, 1, 0);
    mainLayout->addWidget(chartView, 1, 1);
    mainLayout->setColumnStretch(1, 1);
    mainLayout->setColumnStretch(0, 0);
    setLayout(mainLayout);

    resize(1100, 600);


    for(int i = 0;i<acmeSeries->sets().size();i++)
    {
        if(acmeSeries->sets().at(i)->open() < acmeSeries->sets().at(i)->close())
            p1.setColor(Qt::red);
        else if(acmeSeries->sets().at(i)->open() > acmeSeries->sets().at(i)->close())
            p1.setColor(Qt::green);
        else
            p1.setColor(Qt::black);

        acmeSeries->sets().at(i)->setPen(p1);



    }

}

candlestickdatareader.h文件

#ifndef CANDLESTICKDATAREADER_H
#define CANDLESTICKDATAREADER_H

#include <QtCharts/QCandlestickSet>
#include <QtCore/QTextStream>
#include "Types.h"

QT_CHARTS_USE_NAMESPACE

class CandlestickDataReader : public QTextStream
{
public:
    explicit CandlestickDataReader(QIODevice *device);
    ~CandlestickDataReader();

    void readFile(QIODevice *device);
    QCandlestickSet *readCandlestickSet();

    SharesKLineData* readShareKlineData();

};

#endif // CANDLESTICKDATAREADER_H

candlestickdatareader.cpp文件

#include "candlestickdatareader.h"

CandlestickDataReader::CandlestickDataReader(QIODevice *device)
    : QTextStream(device)
{
}

CandlestickDataReader::~CandlestickDataReader()
{
}

void CandlestickDataReader::readFile(QIODevice *device)
{
    QTextStream::setDevice(device);
}

QCandlestickSet *CandlestickDataReader::readCandlestickSet()
{
    //! [1]
    QString line = readLine();
    if (line.startsWith("#") || line.isEmpty())
        return 0;
    //! [1]

    //! [2]
    QStringList strList = line.split(" ", QString::SkipEmptyParts);
    if (strList.count() != 5)
        return 0;
    //! [2]

    //! [3]
    const qreal timestamp = strList.at(0).toDouble();
    const qreal open = strList.at(1).toDouble();
    const qreal high = strList.at(2).toDouble();
    const qreal low = strList.at(3).toDouble();
    const qreal close = strList.at(4).toDouble();
    //! [3]

    //! [4]
    QCandlestickSet *candlestickSet = new QCandlestickSet(timestamp);
    candlestickSet->setOpen(open);
    candlestickSet->setHigh(high);
    candlestickSet->setLow(low);
    candlestickSet->setClose(close);
    //! [4]

    return candlestickSet;
}
SharesKLineData* CandlestickDataReader::readShareKlineData()
{

    //! [1]
    QString line = readLine();

    if (line.startsWith("#") || line.isEmpty())
        return 0;
    //! [1]

    //! [2]
    QStringList strList = line.split(" ", QString::SkipEmptyParts);
    if (strList.count() != 5)
        return 0;
    //! [2]

    //! [3]
    const qreal timestamp = strList.at(0).toDouble();
    const qreal open = strList.at(1).toDouble();
    const qreal high = strList.at(2).toDouble();
    const qreal low = strList.at(3).toDouble();
    const qreal close = strList.at(4).toDouble();
    //! [3]
    SharesKLineData* datas = new SharesKLineData();
    datas->timestamp = timestamp;
    datas->open = open;
    datas->high = high;
    datas->low = low;
    datas->close = close;


    return datas;


}

customtablemodel.h

#ifndef CUSTOMTABLEMODEL_H
#define CUSTOMTABLEMODEL_H

#include <QtCore/QAbstractTableModel>
#include <QtCore/QHash>
#include <QtCore/QRect>

#include "Types.h"

class CustomTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit CustomTableModel(QObject *parent = 0);
    virtual ~CustomTableModel();

    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    Qt::ItemFlags flags(const QModelIndex &index) const;

    void addMapping(QString color, QRect area);
    void clearMapping() { m_mapping.clear(); }

    void addData(SharesKLineData*dataObj);

private:
    QList<QVector<qreal> * > m_data;
    QHash<QString, QRect> m_mapping;

    QList<SharesKLineData> m_klineList;
    QStringList table_header;
    int m_columnCount;
    int m_rowCount;
};



#endif // CUSTOMTABLEMODEL_H

customtablemodel.cpp

#include "customtablemodel.h"
#include <QtCore/QVector>
#include <QtCore/QTime>
#include <QtCore/QRect>
#include <QtCore/QRandomGenerator>
#include <QtGui/QColor>
#include "candlestickdatareader.h"

CustomTableModel::CustomTableModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    m_columnCount = 5;
    m_rowCount = 12;


    // m_data
    for (int i = 0; i < m_rowCount; i++) {
        QVector<qreal>* dataVec = new QVector<qreal>(m_columnCount);
        for (int k = 0; k < dataVec->size(); k++) {
            if (k % 2 == 0)
                dataVec->replace(k, i * 50 + QRandomGenerator::global()->bounded(20));
            else
                dataVec->replace(k, QRandomGenerator::global()->bounded(100));
        }
        m_data.append(dataVec);
    }


    QFile acmeData(":acme");
    if (!acmeData.open(QIODevice::ReadOnly | QIODevice::Text))
    {

    }


    CandlestickDataReader dataReader(&acmeData);

    while (!dataReader.atEnd()) {
        SharesKLineData* tmpData = dataReader.readShareKlineData();

        if(tmpData)
        {
            m_klineList.append(*tmpData);
        }


    }

    m_rowCount = m_klineList.size();
    table_header<< "timestamp"<<"open"<< "high"<<"low"<< "close";
}

CustomTableModel::~CustomTableModel()
{
    qDeleteAll(m_data);
    //qDeleteAll(m_klineList);
}

int CustomTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    //return m_data.count();
    return m_klineList.count();
}

int CustomTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_columnCount;
}

QVariant CustomTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role == Qt::DisplayRole)
    {
        if(orientation == Qt::Horizontal)
        {
            if(table_header.size() > section)

                return table_header[section];
            else
                return QVariant();
        }
    }
}

QVariant CustomTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() > m_klineList.count())
    {
        return QVariant();
    }

    // FIXME: Implement me!
    int nColumn = index.column();
    int row = index.row();  //行号


    if (role == Qt::DisplayRole) {
        //return m_data[index.row()]->at(index.column());
        switch(nColumn)
        {
            case 0:
            return m_klineList[index.row()].timestamp;
                break;
            case 1:
            {
                return m_klineList[index.row()].open;
            }

                break;
            case 2:
                return m_klineList[index.row()].high;
                break;
            case 3:
                return m_klineList[index.row()].low;
                break;
            case 4:
                return m_klineList[index.row()].close;
                break;


        }
    } else if (role == Qt::EditRole) {
        switch(nColumn)
        {
            case 0:
            return m_klineList[index.row()].timestamp;
                break;
            case 1:
            {
                return m_klineList[index.row()].open;
            }

                break;
            case 2:
                return m_klineList[index.row()].high;
                break;
            case 3:
                return m_klineList[index.row()].low;
                break;
            case 4:
                return m_klineList[index.row()].close;
                break;
        }

    } else if (role == Qt::BackgroundRole) {
        for (const QRect &rect : m_mapping) {
            if (rect.contains(index.column(), index.row()))
                return QColor(m_mapping.key(rect));
        }

        // cell not mapped return white color
        return QColor(Qt::white);
    }
    return QVariant();
}

bool CustomTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    int nColumn = index.column();
    if (index.isValid() && role == Qt::EditRole) {
        switch(nColumn)
        {
            case 0:
            m_klineList[index.row()].timestamp = value.toDouble();
                break;
            case 1:
            {
                m_klineList[index.row()].open = value.toDouble();
            }

                break;
            case 2:
               m_klineList[index.row()].high = value.toDouble();
                break;
            case 3:
               m_klineList[index.row()].low = value.toDouble();
                break;
            case 4:
                 m_klineList[index.row()].close = value.toDouble();
                break;
        }
        //m_data[index.row()]->replace(index.column(), value.toDouble());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

Qt::ItemFlags CustomTableModel::flags(const QModelIndex &index) const
{
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

void CustomTableModel::addMapping(QString color, QRect area)
{
    m_mapping.insertMulti(color, area);
}

void CustomTableModel::addData(SharesKLineData *dataObj)
{
    beginResetModel();
    m_klineList.push_back(*dataObj);
    endResetModel();

}

Types.h

#ifndef TYPES_H
#define TYPES_H
#include <QtCore>

typedef struct SharesKLineData
{
    QString day;
    qreal timestamp;
    double open;
    double high;
    double low;
    double close;
    qlonglong  volume;
    double ma_price5;
    quint32 ma_volume5;
    double ma_price10;
    quint32 ma_volume10;
    double ma_price20;
    quint32 ma_volume20;
    double ma_price30;
    quint32 ma_volume30;

}SharesKLineData;

#endif // TYPES_H

main.cpp

#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QCandlestickSeries>
#include <QtCharts/QChartView>
#include <QtCharts/QValueAxis>
#include <QtCore/QDateTime>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QVCandlestickModelMapper>
#include <QtCharts/QHCandlestickModelMapper>

#include "candlestickdatareader.h"
#include "MyTablewidget.h"

QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);




    TableWidget w;
    w.show();
    return a.exec();
}

数据文件就是candlestickchart例子中的acme文件

# Acme Ltd Historical Data (July 2015)
# timestamp,  open,  high,  low,   close
1435708800000 126.90 126.94 125.99 126.60
1435795200000 126.69 126.69 126.69 126.69
1436140800000 124.85 126.23 124.85 126.00
1436227200000 125.89 126.15 123.77 125.69
1436313600000 124.64 124.64 122.54 122.54
1436400000000 123.85 124.06 119.22 120.07
1436486400000 121.94 123.85 121.21 123.28
1436745600000 125.03 125.76 124.32 125.66
1436832000000 126.04 126.37 125.04 125.61
1436918400000 125.72 127.15 125.58 126.82
1437004800000 127.74 128.57 127.35 128.51
1437091200000 129.08 129.62 128.31 129.62
1437350400000 130.97 132.97 130.70 132.07
1437436800000 132.85 132.92 130.32 130.75
1437523200000 121.99 125.50 121.99 125.22
1437609600000 126.20 127.09 125.06 125.16
1437696000000 125.32 125.74 123.90 124.50
1437955200000 123.09 123.61 122.12 122.77
1438041600000 123.38 123.91 122.55 123.38
1438128000000 123.15 123.50 122.27 122.99
1438214400000 122.32 122.57 121.71 122.37
1438300800000 122.60 122.64 120.91 121.30

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gws09876

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值