網站首頁 編程語言 正文
上一章節介紹了關于QGraphicsView的基礎講解,以及簡單的類圖創建,由上一章節中最后展示的動畫效果來看,今年主要講述如何在QGraphicsView架構下,實時拖動鼠標繪制圖形!
今天主要以矩形為例,再來看一下展示效果吧!
功能實現
想要實現鼠標拖拽繪圖的效果,離不開鼠標的三大事件:按下、移動、釋放
那么具體實現實時繪制矩形框的核心流程是什么呢?
第一步:鼠標左鍵點擊,記錄初始點擊位置
第二步:在窗口中移動鼠標,實時獲取鼠標拖動點,根據拖動點繪制指定形狀
第三步:鼠標點擊右鍵釋放鼠標,繪制最終圖形
描述的實現流程很簡單,那么,接下來就實際操作吧!
在進行鼠標點擊繪制的時候,為了兼容多個圖形的實時繪制,這里,不只是用兩個QPoint成員變量記錄鼠標點,而是采取了vector<QPontF>
容器存儲的方式。
例如:三角形圖形,需要三個點才能確定圖形;曲線圖形,是由N多個點才能確定圖形;等等。。。
所以說,這里采用了vector容器進行數據存儲,任何圖形的點都可以進行存儲。
所有的圖形枚舉類型,如下表格:
枚舉類型 | 形狀 |
---|---|
Drawing_Normal | 無圖形繪制 |
Drawing_Circular | 圓形 |
Drawing_StraightLine | 直線 |
Drawing_Rectangular | 矩形 |
Drawing_Triangle | 三角形 |
Drawing_ManyLineSegements | 多線段 |
Drawing_Curve | 曲線 |
今天只講述 矩形:Drawing_Rectangular
1:記錄圖形第一個繪制點
只有鼠標點擊后才能獲取當前點擊點的位置,所以,記錄按下點操作應該是在鼠標的mousePressEvent中實現的。
void QCustomQGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * e) { //TODO:鼠標左鍵,點擊繪制圖形;鼠標右鍵,點擊拖動圖形 QGraphicsScene::mousePressEvent(e); if (e->button() & Qt::LeftButton) { //當圖形處于繪制狀態時 if (m_enumShape!= Drawing_Normal) { //記錄鼠標按下的點 m_vetPoints.push_back(e->scenePos()); } } }
代碼解析:當進入到鼠標按下消息后,只有在左鍵按下狀態時,才做繪圖操作,并且當前形狀枚舉類型有效。
2:實時獲取鼠標最新位置并繪圖
鼠標想要實時繪制,那一定是在鼠標的mouseMoveEvent事件中操作的。
void QCustomQGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * e) { //TODO:鼠標移動時,如果存在有效圖形類型,進行圖形繪制 QGraphicsScene::mouseMoveEvent(e); if (m_enumShape!= Drawing_Normal) { m_pTempLayer->DrawShape(m_enumShape, m_vetPt, e->scenePos()); } }
代碼解析:當鼠標進入到mouseMoveEvent事件后,并且,當前枚舉類型處于有效狀態時,需要實時繪制圖形。
函數DrawShape的講解:
參數1:圖形的枚舉類型,根據不同枚舉,繪制不同的圖形
參數2:vector<QPointF>
傳入已經記錄的鼠標點,可以是多個,但最少是1個。就例如當前繪制矩形來說,該容器中只是存儲了一個繪制點。
參數3:鼠標在mouseMoveEvent中實時拖動點
DrawShape函數實現代碼,如下:
void QTempCanvasLayer::DrawShape(ENUM_DrawingGraphic enumShape, std::vector<QPointF> vetPt, QPointF ptCurrent) { m_pTempCanvasImg->fill(Qt::transparent); m_pTempPainter->setRenderHint(QPainter::Antialiasing, true); m_pTempPainter->setCompositionMode(QPainter::CompositionMode_Source); m_pTempPainter->setPen(QPen(QColor(51, 51, 51), 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin)); switch (enumShape) { case Drawing_Circular: //圓形 break; case Drawing_StraightLine: //直線 break; case Drawing_Rectangular: //矩形 m_pTempPainter->drawRect(QRectF(vetPt[0], ptCurrent)); break; case Drawing_Triangle: //三角形 break; case Drawing_ManyLineSegements: //多線段 break; case Drawing_Curve: //曲線 break; default: break; } update(); }
代碼講解:switch語句之前的內容都是在設置圖形的風格,比如:setRenderHint防止圖形走樣;最需要我們注意的是下面一句代碼:
m_pTempCanvasImg->fill(Qt::transparent);
如果你忘記設置了,當鼠標在拖動繪制圖形時,會導致拖拽線條重疊的效果,就如下面展示效果一樣,如圖所示:
3:釋放繪制點,繪制最終圖形
鼠標事件:mouseReleaseEvent
void QCustomQGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * e) { //TODO:鼠標釋放之后操作 QGraphicsScene::mouseReleaseEvent(e); if (m_enumShape == Drawing_Normal) { return; } //存在有效的圖形類型,進行最終圖形繪制 if (e->button() & Qt::RightButton) { if (m_enumShape == Drawing_Rectangular) { //繪制直線,需要存儲兩個有效點 if (m_vetPt.size() == 2) { this->DrawRealShape(m_vetPt); //如果當前正在繪制圖形,直接清除 this->ClearCurrentDrawingShape(); } } } }
代碼解析:觸發了鼠標釋放事件后,并且是鼠標右鍵點擊(在這里都是以鼠標右鍵點擊作為最終的圖形繪制完成),此時,根據不同的枚舉類型進行圖形繪制。
對于矩形圖形來說,只需要兩個有效的點就會完整對圖形的繪制,其中this->DrawRealShape中進行最終點的繪制。
一個圖形數據繪制成功之后,需要將上一次存儲的臨時點進行清除,以備后續圖形繪制使用,說白了,也就是vector<QPointF>容器需要清除
實現完成了鼠標的三大事件,一個完整的實時鼠標圖形繪制思路已經完成了。
總結
實現鼠標實時繪圖的功能,無論是MFC框架還是Qt框架,基本原理都是一致的,基本上不會離開鼠標的三大事件。
原文鏈接:https://juejin.cn/post/7059340299595677726
相關推薦
- 2022-09-15 一文搞懂C++中繼承的概念與使用_C 語言
- 2022-09-15 Python移動測試開發subprocess模塊項目實戰_python
- 2022-06-22 git工作區暫存區與版本庫基本理解及提交流程全解_其它綜合
- 2023-02-07 C語言可變參數與內存管理超詳細講解_C 語言
- 2022-05-12 Android 截屏實現、屏幕截圖、MediaProjection、ImageReader
- 2022-08-13 Android?Gradle同步優化詳解_Android
- 2022-11-07 PostgreSQL游標與索引選擇實例詳細介紹_PostgreSQL
- 2022-10-22 Redisson?主從一致性問題詳解_Redis
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支