Qt使用QChartView、QFrame、QPushButton画k线

1.使用QChartView作为背景板

2.使用QFrame画最高最低线

3.使用QPushButton画开盘结算线

单个点数据如下:

Qt使用QChartView、QFrame、QPushButton画k线

代码如下:

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);
}

效果如下:

Qt使用QChartView、QFrame、QPushButton画k线

上一篇:Qt styleSheet使用总结


下一篇:Qt信号与槽之自定义信号