wxpython drawtext设置绘制区域_Qt之图表Chart绘制

0efe4aac0113be138304f24cd6b6bcb7.gif

功能

  1. 读写CSV文件,加载数据和导出数据
  2. 支持同时加载多个图表数据
  3. 支持可拉伸图表比例
  4. 支持鼠标悬浮指定刻度位置,显示坐标信息
  5. 支持清屏
  6. 支持显示峰值坐标

效果图

f40fa6b73a66278b069aff77213c04d0.gif

4f1599c42a7a85fefc89b175bb28e302.gif

8b406226c74561ea6f51c73ac8f4f594.gif

b981839c12fa16df06d165275601a2f3.gif

核心代码

void ChartWidget::addChartData(const QList<qreal>& pointy, const QColor& color)
{
	m_pointylst.clear();
	m_pointylst = pointy;
	m_color = color;
}

void ChartWidget::mapCoordinate()
{
	if (0 == m_pointylst.size())
		return;
	//曲线区域高度
	int h = m_height - yoffset - 40;
	qreal max = 0;
	qreal min = 0;
	//最大最小值
	{
		QList<qreal> tmplst = m_pointylst;
		qSort(tmplst.begin(), tmplst.end());
		max = tmplst.last();
		min = tmplst.first();
	}
	//映射每个点坐标
	int distance = max - min;
	int size = m_pointylst.size();
	qreal xscale = interval * 1.0 / size;
	m_pointMaplst.clear();
	for (int i = 0; i < size; i++)
	{
		QPointF point;
		point.setX((i + 1) * m_intervalWidth * xscale + xoffset);
		point.setY(h * (max - m_pointylst[i])* 1.0 / distance + 16);
		m_pointMaplst << point;
	}
}

void ChartWidget::resizeWidthforHeight(int width, int height)
{
	m_width = width;
	m_height = height;
	m_intervalWidth = (width - xoffset * 2) / interval;
	mapCoordinate();
}

QPointF ChartWidget::paintChart(QPainter* painter, QRectF linerect, bool bshowAxis)
{
	painter->save();
	QPen pen;
	pen.setColor(QColor(m_color));
	pen.setStyle(Qt::SolidLine);
	pen.setWidth(2);
	painter->setPen(pen);
	painter->setRenderHint(QPainter::Antialiasing, true);
	QPainterPath path;
	int size = m_pointMaplst.size();
	path.moveTo(m_pointMaplst[0]);
	for (int i = 1; i < size - 1; i++)
	{
		QPointF sp = m_pointMaplst[i];
		QPointF ep = m_pointMaplst[i + 1];
		QPointF c1 = QPointF((sp.x() + ep.x()) / 2, sp.y());
		QPointF c2 = QPointF((sp.x() + ep.x()) / 2, ep.y());
		path.cubicTo(c1, c2, ep);
	}
	painter->drawPath(path);
	painter->restore();

	if (bshowAxis)
	{
		painter->save();
		QPen penAxis;
		penAxis.setColor(QColor(m_color));
		penAxis.setStyle(Qt::SolidLine);
		penAxis.setWidth(1);
		painter->setPen(penAxis);
		painter->setRenderHint(QPainter::Antialiasing, true);
		auto pairPoint = CommonUtils::findPeaks(m_pointylst);
		//极大值
		const QList<int> maxlst = pairPoint.first;
		for (auto iterMax : maxlst)
		{
			QPointF point;
			point = m_pointMaplst.at(iterMax);
			const QString&& num = QString::number(m_pointylst.at(iterMax));
			int numWidth = painter->fontMetrics().width(num);
			point.setX(point.x() - numWidth / 2);
			point.setY(point.y() - 4);
			painter->drawText(point, num);
		}
		//极小值
		const QList<int> minlst = pairPoint.second;
		for (auto iterMin : minlst)
		{
			QPointF point;
			point = m_pointMaplst.at(iterMin);
			const QString&& num = QString::number(m_pointylst.at(iterMin));
			int numWidth = painter->fontMetrics().width(num);
			point.setX(point.x() - numWidth / 2);
			point.setY(point.y() + 14);
			painter->drawText(point, num);
		}
		painter->restore();
	}

	QPointF linePoint;
	// Check if the rectangle surounds any subpath...
	for (int i = 0; i < path.elementCount(); ++i) {
		const QPainterPath::Element &e = path.elementAt(i);
		if (linerect.contains(e))
		{	
			painter->save();
			painter->setPen(Qt::NoPen);
			painter->setBrush(QColor(m_color));
			painter->drawEllipse(e.x - 4, e.y - 4, 8, 8);
			linePoint.setX(e.x);
			linePoint.setY(e.y);
			painter->restore();
		}
	}
	return linePoint;
}
void ChartManagerWidget::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
	QStyleOption opt;
	opt.init(this);
	style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);

	painter.setRenderHint(QPainter::Antialiasing, true);
	//绘制坐标
	QPen linpen;
	linpen.setColor(QColor(102, 102, 102));
	linpen.setStyle(Qt::SolidLine);
	linpen.setWidth(1);
	painter.setPen(linpen);

	//纵坐标
	painter.drawLine(xoffset, height() - yoffset, width() - xoffset, height() - yoffset);
	//横坐标
	int intervalWidth = (width() - xoffset * 2) / 80;
	for (int i = 0; i <= 80; i++){
		if (i == 0){
			painter.drawText(i * intervalWidth + xoffset, height() - 5, QString("0"));
		}
		else if (i % 5 == 0){
			const QString&& num = QString("%1").arg(i);
			int numWidth = painter.fontMetrics().width(num);
			painter.drawText(i * intervalWidth + xoffset - numWidth / 2, height() - 5, num);
			painter.drawLine(i * intervalWidth + xoffset, height() - 21, i * intervalWidth + xoffset, height() - 26);
		}
	}

	//绘制线轴
	qreal lineNum = -1;
	QRectF linerect;
	int chartWidgetSize = m_chartWidgetlst.size();
	int linesize = m_lineRect.size();
	if (chartWidgetSize > 0)
	{
		for (int index = 0; index < linesize; index++)
		{
			if (m_lineRect[index].contains(m_mousepoint))
			{
				linerect.setX(m_linePosx[index]);
				linerect.setY(10);
				linerect.setWidth(1);
				linerect.setHeight(height() - 40);
				painter.drawLine(m_linePosx[index], 10, m_linePosx[index], height() - 30);
				lineNum = (m_linePosx[index] - xoffset) * 1.0 / intervalWidth;
			}
		}
	}

	int curH = 16;
	int maxWidth = 80;
	QList<QString> linepointLst;
	for (int index = 0; index < m_chartWidgetlst.size(); index++){
		painter.save();
		linpen.setColor(m_chartWidgetlst.at(index)->getColor());
		linpen.setStyle(Qt::SolidLine);
		linpen.setWidth(3);
		painter.setPen(linpen);
		QFont font = painter.font();
		font.setFamily(QString::fromLocal8Bit("微软雅黑"));
		painter.setFont(font);
		painter.drawText(4, curH, QString::fromLocal8Bit("曲线%1:").arg(index + 1));
		painter.drawLine(48, curH - 4, 88, curH - 4);
		painter.restore();
		QPointF linePoint = m_chartWidgetlst.at(index)->paintChart(&painter, linerect, m_bShowAxis);
		QString text = QString::fromLocal8Bit("曲线%1:(%2, %3)").arg(index + 1).arg(lineNum).arg(linePoint.y());
		int numWidth = painter.fontMetrics().width(text);
		maxWidth = qMax(maxWidth, numWidth);
		linepointLst << text;
		curH += 16;
	}

	//绘制气泡
	if (lineNum != -1)
	{
		painter.save();
		QPointF rectpoint = m_mousepoint + QPoint(20, 0);
		if (rectpoint.x() + maxWidth + 12 >= this->width()){
			rectpoint.setX(m_mousepoint.x() - 32 - maxWidth);
		}

		painter.setOpacity(0.95);
		painter.setBrush(Qt::gray);
		painter.setPen(Qt::NoPen);
		painter.drawRoundedRect(rectpoint.x(), rectpoint.y(), maxWidth + 12, linepointLst.size() * 20 + 12, 2, 2);
		for (int index = 0; index < linepointLst.size();index++)
		{
			painter.setPen(Qt::white);
			QFont font = painter.font();
			font.setFamily(QString::fromLocal8Bit("微软雅黑"));
			painter.setFont(font);
			painter.setOpacity(1);
			painter.drawText(QRect(rectpoint.x() + 6, rectpoint.y() + index * 20 + 6, maxWidth, 20), Qt::AlignLeft | Qt::AlignVCenter, linepointLst[index]);
		}
		painter.restore();
	}
}

void ChartManagerWidget::mouseMoveEvent(QMouseEvent *event)
{
	m_mousepoint = this->mapFromGlobal(QCursor::pos());
	update();
	QWidget::mouseMoveEvent(event);
}

void ChartManagerWidget::resizeEvent(QResizeEvent *event)
{
	m_linePosx.clear();
	m_lineRect.clear();
	int intervalWidth = (width() - xoffset * 2) / 80;
	for (int i = 0; i <= 80; i++){
		if (i % 5 == 0){
			QRect rect(i * intervalWidth + xoffset - 10, 20, 20, height() - 40);
			m_linePosx << i * intervalWidth + xoffset;
			m_lineRect << rect;
		}
	}
	for (auto iter : m_chartWidgetlst){
		iter->resizeWidthforHeight(event->size().width(), event->size().height());
	}
}

结尾

更新精彩Qt作品内容,欢迎关注雨田哥的知乎
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值