Qt中QGraphicsView架构下实时鼠标绘制图形

打印 上一主题 下一主题

主题 835|帖子 835|积分 2505

上一章节先容了关于QGraphicsView的基础解说,以及简单的类图创建,由上一章节中最后展示的动画效果来看,今年主要讲述如何在QGraphicsView架构下,实时拖动鼠标绘制图形!
今天主要以矩形为例,再来看一下展示效果吧!

功能实现

想要实现鼠标拖拽画图的效果,离不开鼠标的三大事件:按下、移动、释放
那么具体实现实时绘制矩形框的核心流程是什么呢?
第一步:鼠标左键点击,记录初始点击位置
第二步:在窗口中移动鼠标,实时获取鼠标拖动点,根据拖动点绘制指定形状
第三步:鼠标点击右键释放鼠标,绘制最终图形
形貌的实现流程很简单,那么,接下来就现实操作吧!
在进行鼠标点击绘制的时候,为了兼容多个图形的实时绘制,这里,不但是用两个QPoint成员变量记录鼠标点,而是接纳了vector<QPontF>容器存储的方式。
比方:三角形图形,需要三个点才能确定图形;曲线图形,是由N多个点才能确定图形;等等。。。
所以说,这里接纳了vector容器进行数据存储,任何图形的点都可以进行存储。
全部的图形罗列类型,如下表格:

今天只讲述 矩形:Drawing_Rectangular
1:记录图形第一个绘制点

只有鼠标点击后才能获取当前点击点的位置,所以,记录按下点操作应该是在鼠标的mousePressEvent中实现的。
  1. void QCustomQGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * e)
  2. {
  3.         //TODO:鼠标左键,点击绘制图形;鼠标右键,点击拖动图形
  4.         QGraphicsScene::mousePressEvent(e);
  5.         if (e->button() & Qt::LeftButton)
  6.         {
  7.                 //当图形处于绘制状态时
  8.                 if (m_enumShape!= Drawing_Normal)
  9.                 {
  10.                         //记录鼠标按下的点
  11.                         m_vetPoints.push_back(e->scenePos());
  12.                 }
  13.         }
  14. }
复制代码
代码解析:当进入到鼠标按下消息后,只有在左键按下状态时,才做画图操作,并且当前形状罗列类型有效。
2:实时获取鼠标最新位置并画图

鼠标想要实时绘制,那肯定是在鼠标的mouseMoveEvent事件中操作的。
  1. void QCustomQGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * e)
  2. {
  3.         //TODO:鼠标移动时,如果存在有效图形类型,进行图形绘制
  4.         QGraphicsScene::mouseMoveEvent(e);
  5.         if (m_enumShape!= Drawing_Normal)
  6.         {
  7.                 m_pTempLayer->DrawShape(m_enumShape, m_vetPt, e->scenePos());
  8.         }
  9. }
复制代码
代码解析:当鼠标进入到mouseMoveEvent事件后,并且,当前罗列类型处于有效状态时,需要实时绘制图形。
函数DrawShape的解说
参数1:图形的罗列类型,根据差别罗列,绘制差别的图形
参数2:vector<QPointF>传入已经记录的鼠标点,可以是多个,但最少是1个。就比方当前绘制矩形来说,该容器中只是存储了一个绘制点。
参数3:鼠标在mouseMoveEvent中实时拖动点
DrawShape函数实当代码,如下:
  1. void QTempCanvasLayer::DrawShape(ENUM_DrawingGraphic enumShape, std::vector<QPointF> vetPt, QPointF ptCurrent)
  2. {
  3.         m_pTempCanvasImg->fill(Qt::transparent);
  4.         m_pTempPainter->setRenderHint(QPainter::Antialiasing, true);
  5.         m_pTempPainter->setCompositionMode(QPainter::CompositionMode_Source);
  6.         m_pTempPainter->setPen(QPen(QColor(51, 51, 51), 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin));
  7.         switch (enumShape)
  8.         {
  9.         case Drawing_Circular: //圆形
  10.                 break;
  11.         case Drawing_StraightLine: //直线
  12.                 break;
  13.         case Drawing_Rectangular: //矩形
  14.                 m_pTempPainter->drawRect(QRectF(vetPt[0], ptCurrent));
  15.                 break;
  16.         case Drawing_Triangle: //三角形
  17.                 break;
  18.         case Drawing_ManyLineSegements: //多线段
  19.                 break;
  20.         case Drawing_Curve: //曲线
  21.                 break;
  22.         default:
  23.                 break;
  24.         }
  25.         update();
  26. }
复制代码
代码解说:switch语句之前的内容都是在设置图形的风格,比如:setRenderHint防止图形走样;最需要我们注意的是下面一句代码:
  1. m_pTempCanvasImg->fill(Qt::transparent);
复制代码
如果你忘记设置了,当鼠标在拖动绘制图形时,会导致拖拽线条重叠的效果,就如下面展示效果一样,如图所示:

3:释放绘制点,绘制最终图形

鼠标事件:mouseReleaseEvent
  1. void QCustomQGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * e)
  2. {
  3.         //TODO:鼠标释放之后操作
  4.         QGraphicsScene::mouseReleaseEvent(e);
  5.         if (m_enumShape == Drawing_Normal)
  6.         {
  7.                 return;
  8.         }
  9.         //存在有效的图形类型,进行最终图形绘制
  10.         if (e->button() & Qt::RightButton)
  11.         {
  12.                 if (m_enumShape == Drawing_Rectangular)
  13.                 {
  14.                         //绘制直线,需要存储两个有效点
  15.                         if (m_vetPt.size() == 2)
  16.                         {
  17.                                 this->DrawRealShape(m_vetPt);
  18.                                 //如果当前正在绘制图形,直接清除
  19.                                 this->ClearCurrentDrawingShape();
  20.                         }
  21.                 }
  22.         }
  23. }
复制代码
代码解析:触发了鼠标释放事件后,并且是鼠标右键点击(在这里都是以鼠标右键点击作为最终的图形绘制完成),此时,根据差别的罗列类型进行图形绘制。
对于矩形图形来说,只需要两个有效的点就会完整对图形的绘制,其中`this->DrawRealShape`中进行最终点的绘制。
一个图形数据绘制乐成之后,需要将上一次存储的暂时点进行扫除,以备后续图形绘制利用,说白了,也就是vector<QPointF>容器需要扫除
实现完成了鼠标的三大事件,一个完整的实时鼠标图形绘制思路已经完成了。
总结

实现鼠标实时画图的功能,无论是MFC框架还是Qt框架,基本原理都是同等的,基本上不会离开鼠标的三大事件。
我是糯诺诺米团,一名C++开辟步调媛~

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美食家大橙子

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表