網站首頁 編程語言 正文
做慣了靜態圖,今天來搞一搞動態圖吧,首先來個最基礎的功能:如果讓一個控件拖動起來。
展示效果:
按照以往簡單的做法,使用mouseMoveEvent、mousePressEvent、mouseReleaseEvent也是可以實現的。這是最基礎的移動做法。
今天,不使用那種簡單的做法,采用Qt一種特有的拖動方法來實現!
使用QDropEvent實現拖拽事件。
實現控件拖拽的流程,如下:
1:創建一個控件,這里使用QLabel控件。
2:選中需要拖拽的控件
3:重寫拖拽事件。
根據上述操作流程,來實現一個控件的拖拽吧!
1.設置窗口拖拽屬性
在Qt中,默認是不響應拖拽消息的,這跟mouseMoveEvent消息默認不響應是一樣的,必須明確調用,告訴窗口,需要響應此消息。
this->setAcceptDrops(true);
2.創建初始控件
創建一個初始控件,用于初始拖動使用。
QLabel *labIcon = new QLabel(this); labIcon->setText(""); labIcon->setPixmap(QPixmap(":/QDragSingleLabel/image/boat.png")); labIcon->move(10, 10); labIcon->show(); labIcon->setAttribute(Qt::WA_DeleteOnClose);
偷懶起見,對QLabel控件設置了窗口關閉銷毀的功能,很是方便。
3.選中控件進行拖動
鼠標在控件上按下,開始做拖動操作;當鼠標抬起時,不進行拖動操作。
3.1響應mousePressEvent事件
需要知道鼠標是否點擊到控件上
這里需要特殊注意的是:QLabel是一個靜態控件,正常情況下是不會響應鼠標選中效果的。
此時,需要響應QWidget鼠標按下的事件,將鼠標點擊的點轉換成是否選中QLabel控件,側面實現數據點擊控件效果。
QLabel *child = static_cast<QLabel*>(childAt(event->pos())); if(!child) { //不是QLabel控件,不進行處理 return; }
QWidget::childAt(const QPoint& p)const;
說明:返回窗口小部件自身坐標系統中p點處的可見子窗口小部件。
查詢到有效QLabel指針后,創建一個可存儲在剪貼板中的信息,通過拖放機制進行傳輸的。這里采用:QMimeData
類實現。
優勢該類可以確保信息在應用程序之間安全傳輸,并且可以在相同的應用程序內復制。
創建該類并將QLabel中的數據傳入到類中,用于做拖拽使用。
QMimeData *mimeData = new QMimeData; mimeData->setData(qsEnum, itemData);
設置數據。
qsEnum:類型:QString。
在這里可以設置任意字符串,只要保證在拖拽消息時用的一個字符串就可以。為了方便統一,將該字符串做了統一設置。
const QString qsEnum = "zhongGuoHaoGongMin";//自定義數據類型
itemData:類型:QByteArray。
對QMimeData傳入的數據,這里存放了QLabel的圖片以及顯示位置。
QPixmap pixmap = *child->pixmap(); QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << pixmap << QPoint(event->pos() - child->pos());
上述內容準備就緒后,創建拖拽類,用于數據拖拽。
QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(event->pos() - child->pos());
將數據傳遞給拖動對象,設置將在操作期間與光標一起顯示的像素圖,并定義一個熱點的位置,該熱點將像素圖的位置置于光標之下。
繪制拖動的位置,這里采用了QPainter繪制機制
QPixmap tempPixmap = pixmap; QPainter painter; painter.begin(&tempPixmap); painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127)); painter.end(); child->setPixmap(tempPixmap);
開始拖動操作,調用QDrag::exec()
;
3.2判斷控件拖動
目前只有一個控件可以拖動,那么,當創建多個拖動控件時,該如何判斷要拖動哪個呢?
這時候,在創建QMimeData傳入的自定義數據類型就起到作用了。
當數據類型是qsEnum時,進行判斷,如果不是,不進行判斷。
if (event->mimeData()->hasFormat(qsEnum)) { //進行判斷 } else { event->ingnore(); //忽略判斷 }
事件:dragEnterEvent、dragMoveEvent、dropEvent都需要這樣判斷。
3.3事件處理
當前是匹配的自定義數據類型時,并且是該資源是,接受拖動進入事件,并設置當前為拖動事件。
if (event->source() == this) { event->setDropAction(Qt::MoveAction); event->accept(); }
否則設置執行操作并接收該事件
else { event->acceptProposedAction(); }
3.4結束拖動
結束拖動,響應事件:virtual void dropEvent(QDropEvent *event)override;
除了處理操作3中的事件處理,還需要當鼠標結束操作時,需要在新的位置上重新創建QLabel控件。并將鼠標按下時創建的QMimeData數據獲取出來,顯示到新創建的QLabel控件上。
QByteArray itemData = event->mimeData()->data(qsEnum); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QPixmap pixmap; QPoint offset; dataStream >> pixmap >> offset; QLabel *newIcon = new QLabel(this); newIcon->setPixmap(pixmap); newIcon->move(event->pos() - offset); newIcon->show(); newIcon->setAttribute(Qt::WA_DeleteOnClose);
dropEvent消息是什么時候被觸發呢?
當鼠標左鍵彈起時,說明結束了控件拖動事件,需要調用dropEvent并重新創建控件,顯示新位置。
Qt::DropAction n = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction); if (n == Qt::MoveAction) { //結束操作 child->close(); } else { //繼續拖動控件,實時顯示新位置 child->show(); child->setPixmap(pixmap); }
原文鏈接:https://juejin.cn/post/7111515493227298852
相關推薦
- 2022-11-14 Swift?指針底層探索分析_Swift
- 2022-10-20 VS?Code?常用自定義配置代碼規范保存自動格式化_相關技巧
- 2022-10-26 Python中打包和解包(*和**)的使用詳解_python
- 2022-10-05 使用python?matplotlib?contour畫等高線圖的詳細過程講解_python
- 2022-10-06 Python+Scipy實現自定義任意的概率分布_python
- 2022-03-31 解決在window下執行SQLSERVER定時備份的問題_MsSql
- 2022-12-12 Flutter手機權限檢查與申請實現方法詳解_Android
- 2022-07-09 使用Jquery操作Cookies_jquery
- 最近更新
-
- 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同步修改后的遠程分支