1.使用QChartView作为背景板
2.使用QFrame画最高最低线
3.使用QPushButton画开盘结算线
单个点数据如下:
代码如下:
std::vector <QFrame *> m_vMidline; //收集K线中线用于清除
std::vector <QPushButton *> m_vCandle; //收集K线用于清除
QtCharts::QChartView *m_KLineView; //k线主图(k线图与其他图分离)
QCategoryAxis *m_caKLineX = NULL;
QCategoryAxis *m_caKLineY = NULL;
void CKLine::drawKLine(std::vector<P122372::CProtocolHisPoint> vPoints)
{
if(!m_vMidline.empty())
{
for(int i=0; i<m_vMidline.size(); i++)
{
delete m_vMidline[i];
m_vMidline[i] = NULL;
}
m_vMidline.clear();
}
if(!m_vCandle.empty())
{
for(int i=0; i<m_vCandle.size(); i++)
{
delete m_vCandle[i];
m_vCandle[i] = NULL;
}
m_vCandle.clear();
}
if(m_caKLineX)
{
delete m_caKLineX;
m_caKLineX = NULL;
}
m_caKLineX = new QCategoryAxis(); //x轴
if(m_caKLineY)
{
delete m_caKLineY;
m_caKLineY = NULL;
}
m_caKLineY = new QCategoryAxis(); //y轴
auto qsYangSheet = "background-color:rgba(0,0,0);border-color:rgb(255,0,0);border-width:1px"; //开盘结算阳线样式
auto qsYinSheet = "background-color:rgba(0,255,255);border-color:rgb(0,255,255);border-width:1px"; //开盘结算阴线样式
auto qsYangSheet1 = "border-color:rgb(255,0,0);border-width:1px"; //最高最低阳线样式
auto qsYinSheet1 = "border-color:rgb(0,255,255);border-width:1px"; //最高最低阴线样式
float fDataHigh = vPoints[0].High; //数据最大最高价
float fDataLow = vPoints[0].Low; //数据最小最低价
for(int i=0; i<vPoints.size(); i++) //默认只画100个k线
{
if(fDataHigh < vPoints[i].High)
{
fDataHigh = vPoints[i].High;
}
if(fDataLow > vPoints[i].Low)
{
fDataLow = vPoints[i].Low;
}
}
float fPoor = fDataHigh - fDataLow;
float fDrawHigh = fDataHigh + fPoor / 80; //画图最大最高价
float fDrawLow = fDataLow - fPoor / 80; //画图最小最低价
float fX = 12; //单个k线起始x坐标
for(int i=0; i<vPoints.size(); i++)
{
float fY; //k线y坐标
float fWidth = 11; //k线宽度
float fHeight; //k线高度
float fVerHeight; //k线中线高度
float fVerY; //k线中线y坐标
QFrame *pVerLine = new QFrame(m_KLineView); //单个k线中线
pVerLine->setFrameStyle(QFrame::VLine|QFrame::Plain);
m_vMidline.push_back(pVerLine);
QPushButton *pCandleLabel = new QPushButton(m_KLineView); //单个k线(使用QPushButton做后期触发)
m_vCandle.push_back(pCandleLabel);
P122372::CProtocolHisPoint& pPoint = vPoints[i];
if(!pPoint.CheckValid())
{
continue;
}
fHeight = fabs(820.0 / (fDrawHigh - fDrawLow) * (pPoint.Open - pPoint.Close));
if(fHeight < 1) //小于1高度的QPushButton无法显示
{
fHeight = 1;
}
fVerHeight = fabs(820.0 / (fDrawHigh - fDrawLow) * (pPoint.High - pPoint.Low));
if(pPoint.Open > pPoint.Close) //阴线中线
{
pCandleLabel->setStyleSheet(qsYinSheet);
pVerLine->setStyleSheet(qsYinSheet1);
}
else if(pPoint.Open < pPoint.Close) //阳线中线
{
pCandleLabel->setStyleSheet(qsYangSheet);
pVerLine->setStyleSheet(qsYangSheet1);
}
else //十字线
{
fWidth = 50;
}
if(pPoint.Open >= pPoint.Close)
{
fY = 820.0 * (fDrawHigh - pPoint.Open) / (fDrawHigh - fDrawLow);
}
else if(pPoint.Open < pPoint.Close)
{
fY = 820.0 * (fDrawHigh - pPoint.Close) / (fDrawHigh - fDrawLow);
}
fVerY = 820.0 * (fDrawHigh - pPoint.High) / (fDrawHigh - fDrawLow);
pVerLine->setGeometry(fX+(fWidth-1)/2, fVerY, 1, fVerHeight);
pVerLine->show();
pCandleLabel->setGeometry(fX, fY, fWidth, fHeight);
pCandleLabel->show();
fX += fWidth + 1; //1为k线之间的间隙
}
//网格线设置
m_caKLineX->setGridLineVisible(true);
m_caKLineX->setGridLinePen(QPen(QBrush(QColor(64, 64, 64)), 1, Qt::DashLine));
m_caKLineX->setTickCount(6); //横网格数量
m_caKLineY->setGridLineVisible(true);
m_caKLineY->setGridLinePen(QPen(QBrush(QColor(64, 64, 64)), 1, Qt::DashLine));
m_caKLineY->setTickCount(21); //纵网格数量
m_caKLineX->setRange(vPoints.begin()->DateTime/1000, (vPoints.end()-1)->DateTime/1000);
m_caKLineY->setRange(fDrawLow, fDrawHigh);
//设置x轴时间数据
for(int i=0; i<7; i++)
{
int iLong = vPoints.size() / 7;
auto iDateTime = vPoints[i*iLong].DateTime/1000;
m_caKLineX->append(QDateTime::fromTime_t(iDateTime).toString("yyyy-MM-dd"), iDateTime);
}
//设置y轴时间数据
float fYLong = (fDrawHigh - fDrawLow) / 20;
for(float i=0; i<20; i++)
{
m_caKLineY->append(QString("%1").arg(fDrawLow+fYLong*i), fDrawLow+fYLong*i);
}
m_caKLineY->append(QString("%1").arg(fDrawHigh), fDrawHigh);
m_caKLineX->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue); //对齐
m_caKLineY->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue);
//设置坐标轴标签的字体
QFont labelFont("SimSun", 10);
m_caKLineX->setLabelsFont(labelFont);
m_caKLineY->setLabelsFont(labelFont);
m_caKLineX->setLabelsColor(QColor(155, 173, 173));
m_caKLineY->setLabelsColor(QColor(155, 173, 173));
m_KLineView->chart()->addAxis(m_caKLineX, Qt::AlignBottom); //XY轴的位置是下和右
m_KLineView->chart()->addAxis(m_caKLineY, Qt::AlignRight);
}
效果如下: