您好,欢迎来到汇智旅游网。
搜索
您的当前位置:首页Qt 双缓冲绘图

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

参考


因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- hzar.cn 版权所有 赣ICP备2024042791号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务