//创建股票图
//为了显示股票图表,我们首先创建 QCandlestickSeries 来处理每日数据。
//我们还指定了自定义增加和减少的车身颜色。
QCandlestickSeries *acmeSeries = new QCandlestickSeries();
acmeSeries->setName("Acme Ltd");
acmeSeries->setIncreasingColor(QColor(Qt::green));
acmeSeries->setDecreasingColor(QColor(Qt::red));
//QFile 用于访问保存非连续数据的文本文件。
//CandlestickDataReader 是一个辅助类,
//用于读取文本文件并从数据中查找开盘价、最高价、最低价、收盘价和时间戳值。
//CandlestickDataReader 将在后面更详细地解释。
//方法 readCandlestickSet() 读取值并将它们设置为该方法为调用者返回的 QCandlestickSet 项。
//返回的 QCandlestickSet 项目被添加到系列中。
//我们还保存自定义类别列表供以后使用。
//成功则返回真; 否则返回假
QFile acmeData(":acme");
if(!acmeData.open(QIODevice::ReadOnly | QIODevice::Text))
return 1;
QStringList categories;
CandlestickDataReader dataReader(&acmeData);
while(!dataReader.atEnd())
{
QCandlestickSet *set = dataReader.readCandlestickSet();
if(set)
{
acmeSeries->append(set);
categories<<QDateTime::fromMSecsSinceEpoch(set->timestamp()).toString("dd");
}
}
//下面,创建了一个新的 QChart 实例,并将之前创建的系列对象添加到其中。
//我们还定义了一个标题,并将动画设置为 QChart::SeriesAnimation。
QChart *chart = new QChart();
chart->addSeries(acmeSeries);
chart->setTitle("Acme Ltd Hostorical Data");
chart->setAnimationOptions(QChart::SeriesAnimations);
//在这里,我们要求图表为我们的演示文稿创建默认轴。
//然后,我们通过从图表中查询轴的指针来为横轴设置自定义类别
//然后从之前保存的自定义类别列表中设置类别
//我们还通过从图表中查询轴的指针来设置垂直轴的范围
//然后设置该轴的最小值和最大值。
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);
//下面,我们将图例设置为可见并将其放置在图表底部。
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);
//最后,我们将图表添加到视图中。
//我们还为图表视图打开了抗锯齿功能。
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
//图表已准备好显示。 我们将图表设置为窗口的中央小部件。
//我们还设置图表窗口的大小并显示它。
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(800,600);
window.show();
//这里,详细解释了 readCandlestickSet() 方法。
//首先,从文件中读取一行,拒绝任何以 # 开头的行,因为它们被视为注释行。
QString line = readLine();
if(line.startsWith("#") || line.isEmpty())
return 0;
//在文件中,数据按空格分隔的数字序列排列。
//在此代码段中,该行被拆分为单个数字字符串,这些字符串存储在 QStringList 中。
QStringList strList = line.split(QLatin1Char(' '),Qt::SkipEmptyParts);
if(strList.count() != 5)
return 0;
//要从连续数据中选择值,请使用以下代码。
//strList 中的值按以下顺序存储:时间戳、开盘价、最高价、最低价、收盘价。
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();
//最后,以下代码段展示了如何创建一个新的 QCandlestickSet
//并为其提供所有必要的值。
QCandlestickSet *candlestickSet = new QCandlestickSet(timeStamp);
candlestickSet->setOpen(open);
candlestickSet->setHigh(high);
candlestickSet->setLow(low);
candlestickSet->setClose(close);
main.cpp
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QCandlestickSeries>
#include <QtCharts/QChartView>
#include <QtCharts/QValueAxis>
#include <QtCore/QDateTime>
#include <QtCore/QFile>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include "candlestickdatareader.h"
//QCandlestickSeries
//此类充当单个股票图项目的容器。
//使用 QBarCategoryAxis 时,每个项目都被绘制到自己的类别中。
//QDateTimeAxis 和 QValueAxis 可以用作 QBarCategoryAxis 的替代品。
//在这种情况下,每个烛台项目都是根据其时间戳值绘制的。
//注意:时间戳在 QCandlestickSeries 中必须是唯一的。
//使用 QBarCategoryAxis 时,仅绘制第一个共享时间戳的烛台项目。
//如果图表包含 QCandlestickSeries 的多个实例,则来自共享时间戳的不同系列的项目将被绘制到同一类别。
//使用 QValueAxis 或 QDateTimeAxis 时,共享时间戳的烛台项目将相互重叠
QT_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//! [1]
QCandlestickSeries *acmeSeries = new QCandlestickSeries();
acmeSeries->setName("Acme Ltd");
//此属性保存递增烛台项目主体的颜色。
//当收盘价高于开盘价时,烛台会增加。
//默认情况下,此属性设置为画笔颜色。
//当属性设置为无效颜色值时,也会使用默认颜色。
acmeSeries->setIncreasingColor(QColor(Qt::green));
//此属性保存下降烛台项目主体的颜色。
//当烛台的开盘价高于收盘价时,烛台会下降。
//默认情况下,此属性设置为笔刷颜色
//,alpha 通道设置为 128。
//,alpha 通道设置为 128。
acmeSeries->setDecreasingColor(QColor(Qt::red));
//! [1]
//! [2]
QFile acmeData(":acme");
if (!acmeData.open(QIODevice::ReadOnly | QIODevice::Text))
return 1;
QStringList categories;
CandlestickDataReader dataReader(&acmeData);
while (!dataReader.atEnd()) {
QCandlestickSet *set = dataReader.readCandlestickSet();
if (set) {
acmeSeries->append(set);
categories << QDateTime::fromMSecsSinceEpoch(set->timestamp()).toString("dd");
}
}
//! [2]
//! [3]
QChart *chart = new QChart();
chart->addSeries(acmeSeries);
chart->setTitle("Acme Ltd Historical Data (July 2015)");
chart->setAnimationOptions(QChart::SeriesAnimations);
//! [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]
//! [7]
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(800, 600);
window.show();
//! [7]
return a.exec();
}
candlestickdatareader.h
#ifndef CANDLESTICKDATAREADER_H
#define CANDLESTICKDATAREADER_H
#include <QtCharts/QCandlestickSet>
#include <QtCore/QTextStream>
QT_USE_NAMESPACE
class CandlestickDataReader : public QTextStream
{
public:
explicit CandlestickDataReader(QIODevice *device);
~CandlestickDataReader();
void readFile(QIODevice *device);
QCandlestickSet *readCandlestickSet();
};
#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(QLatin1Char(' '), Qt::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;
}