Qt 双缓冲绘图

Qt双缓冲绘图

1. 双缓冲绘图

双缓冲绘图就是绘图时先将绘画过程的图形暂存在临时画布上,当绘制完成后一次性输出到显示设备。

2. 程序实现

下面以简单的绘画板程序为例介绍双缓冲绘图的实现。程序实现自由画线、画矩形、画线段。
在这里插入图片描述

首先在头文件中添加画布变量,与鼠标起始点、终点坐标变量,工作模式变量,开始绘图标志

	QPixmap m_pic;			//图片
	QPixmap m_tempPic;		//辅助画布 用于显示绘制过程
	
	// 鼠标起始点 结束点
	QPoint m_startPoint;
	QPoint m_endPoint;
	
	bool m_DrawFlag = false; //绘图标志

	//工作模式
	enum workMode
	{
		MODE_DRAW_LINE,			//画线
		MODE_DRAW_RECT,			//画矩形
		MODE_DRAW_LINES,		//画线段

	};
	workMode m_modeFlag;//工作模式
	

需要重新实现鼠标事件mousePressEvent,mouseMoveEvent,mouseReleaseEvent,和绘图事件paintEvent

	virtual void paintEvent(QPaintEvent* e);
	virtual void mouseMoveEvent(QMouseEvent* e);
	virtual void mousePressEvent(QMouseEvent* e);
	virtual void mouseReleaseEvent(QMouseEvent* e);

mousePressEvent表示按下鼠标开始绘图,同时将当前图像存入临时画布m_tempPic,所有的过程绘制都在m_tempPic中进行。

	//鼠标点击事件
	void workZoneWidget::mousePressEvent(QMouseEvent* e)
	{
		m_startPoint = e->pos(); //获取起始点
		m_DrawFlag = true;	//开始绘图

		//将以前pic中的内容复制到tempPic中,保证以前的内容不消失
		m_tempPic = m_pic;	//准备备份图片
	}

mouseMoveEvent记录每次微小移动的落点为结束点,在paintEvent中绘制拖动过程。

	//鼠标移动事件
	void workZoneWidget::mouseMoveEvent(QMouseEvent* e)
	{
		if (e->buttons() & Qt::LeftButton) //鼠标左键按下的同时移动鼠标    
		{
			m_endPoint = e->pos();
			update(); //产生绘图事件  
		}
	
	}

mouseReleaseEvent鼠标释放表示一次绘图结束,同时记录终点,通知绘图。

	//鼠标释放事件
	void workZoneWidget::mouseReleaseEvent(QMouseEvent* e)
	{
		if (e->button() == Qt::LeftButton) //鼠标左键释放    
		{
			m_endPoint = e->pos();
			update();//产生绘图事件  
			m_DrawFlag = false;	//结束绘图
		}

	}

paintEvent绘图事件中主要是根据鼠标事件中获得的坐标在辅助画布中绘图,当绘图结束是将辅助画布中的最终图片绘制到绘图区域上。

void workZoneWidget::paintEvent(QPaintEvent* e)
{
	QPainter painter(this);  //显示区域画家
	//设置抗锯齿
	painter.setRenderHints(QPainter::SmoothPixmapTransform |
							QPainter::Antialiasing); 

	//双缓冲绘图
	int x, y, w, h; 	//绘制矩形相关变量
	x = m_startPoint.x();
	y = m_startPoint.y();
	w = m_endPoint.x() - x;
	h = m_endPoint.y() - y;
	
	if (m_DrawFlag) //正在绘图
	{
		//如果正在绘图,就在辅助画布上绘制
		//绘制的是拖动的过程
		QPainter pp(&m_tempPic); //辅助画布画家
		
		switch (m_modeFlag) //判断绘画模式
		{
		case MODE_DRAW_LINE: //自由绘图
			pp.drawLine(m_startPoint, m_endPoint); //画线
			//使结束点作为下一次的起点 画连续曲线 屏蔽为画直线段
			m_startPoint = m_endPoint; 
			break;
		case MODE_DRAW_LINES:
			//用m_pic清屏 避免每次过程叠加 不适用于连续过程 如画曲线 
			//可以屏蔽此句看看效果
			pp.drawPixmap(0, 0, m_pic);//在m_tempPic 上重绘一次 m_pic 实现清屏
			
			pp.drawLine(m_startPoint, m_endPoint); //画线
			//m_startPoint = m_endPoint; 
			break;
		case MODE_DRAW_RECT:
			//用m_pic清屏 避免每次过程叠加 不适用于连续过程 如画曲线 
			pp.drawPixmap(0, 0, m_pic);//在m_tempPic 重绘一次 m_pic 实现清屏
			
			pp.drawRect(x, y, w, h); //绘制矩形
			break;
		}

		painter.drawPixmap(0, 0, m_tempPic);//工作区显示m_tempPic 即每个拖动过程
	}
	else //绘制完成 刷新图片到显示设备
	{
		if (!m_tempPic.isNull()) //不在绘图 且辅助画布已经画过图片 即 绘画已完成
		{
			m_pic = m_tempPic; // 绘图过程结束 此时m_tempPic为最终绘制图像
			m_tempPic = QPixmap(); //绘制完成清空备份 
		}	

		//刷新图片 到显示区域
		painter.drawPixmap(0, 0, m_pic);
	}
}

参考

Qt 快速入门系列教程(作者:yafeilinux):第17篇 2D绘图(七)涂鸦板
Qt 快速入门系列教程(作者:yafeilinux):第18篇 2D绘图(八)双缓冲绘图

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: QCustomPlot是一个非常有用的Qt C++库,可以用于创建交互式曲线图,散点图,条形图和其他型的图表。在使用QCustomPlot时,可以使用QCPGraph创建波浪图。下面是如何绘制波浪图的步骤: 1. 创建QCustomPlot实例并添加一个轴。 2. 创建QCPGraph实例并将其添加到QCustomPlot。 3. 使用QVector为波浪图提供数据。 4. 调整波浪图的属性,例如线宽,颜色和数据点的形状。 5. 使用QCPItemLine添加水平参考线。 通过这些步骤,可以使用QCustomPlot创建一个具有波浪效果的图表。这种型的图表在许多应用程序常见,例如在实时数据监控和气象预报QCustomPlot是一个非常强大的工具,可以用于绘制各种型的图表和可视化,任何想快速创建交互式和动态图表的开发人员都应该考虑使用它。 ### 回答2: QCustomPlot是一款优秀的C++开源库,可以用于绘制各种形式的2D图形,包括波浪图。使用QCustomPlot绘制波浪图的步骤如下: 1. 由于波浪图通常是随时间变化的,因此需要使用QTimer来定时更新波浪数据。可以使用QVector来存储波浪数据。 2. 在QCustomPlot绘制波浪图需要使用一个曲线图(QCPGraph),可以通过addGraph()函数添加一个曲线图,并设置好曲线图的样式(如线条颜色、粗细等)。 3. 根据时间定时更新波浪数据,并将新的波浪数据添加到曲线图上。可以使用graph()->setData()函数设置曲线图的数据源。 4. 为了实现波浪效果,可以通过设置QCustomPlot的x轴和y轴范围来实现波浪滚动的效果。可以使用axisRect()->setupFullAxesBox()函数来设置坐标轴的范围,axisRect()->setRangeDrag()函数来实现平移,axisRect()->setRangeZoom()函数来实现缩放。 5. 可以通过对QCustomPlot的背景进行绘制来实现海洋的效果。可以使用setBackground()函数设置背景颜色或背景图像。 6. 最后,需要使用replot()函数来将绘图更新到屏幕上。 总之,使用QCustomPlot可以很容易地绘制出趣味性的波浪图,并能方便地实现交互操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值