網站首頁 編程語言 正文
PyQt5的拖放
拖放涉及到的主要的一些類如下所示:
一、拖放的基本原理
1.1 拖放的動作
拖放操作包括兩個動作:
- 拖動(drag)
- 放下(drop 或稱為放置)。
當被拖動時拖動的數據會被存儲為 MIME 類型的對象, MIME 類型使用 QMimeData 類來描述。 MIME 類型通常由剪貼板和拖放系統使用,以識別不同類型的數據。
- 拖動點(drag site):拖動的起始位置。
- 放下點(drop site):被拖動的對象放下的位置,若部件不能接受拖動的對象, Qt 會改變光標的形狀(一個禁用形狀)來向用戶進行說明。
1.2 拖動的啟動和結束
啟動拖放:
拖放通過調用 QDrag::exec()函數而啟動,該函數是一個阻塞函數(但不會阻塞主事件循環),這意味著在拖放操作結束之前,不會返回該函數,調用 QDrag::exec()函數后, Qt 擁有對拖動對象的所有權,并會在必要時將其刪除。
結束拖放:
當用戶放下拖動或取消拖動操作時結束拖放。
1.3 拖放產生的過程和事件
啟動拖放后,會使數據被拖動,這時需要按住鼠標按鍵才能拖動需要拖動的數據,松開鼠標按鍵時意味著拖動結束。
默認情況下,部件不接受放下事件。使用 QWidget::setAcceptDrops()函數可設置部件是否接受放下事件(即,拖放完成時發送的事件)。只有在部件接受放下事件的情形下,才會產生以下事件。
QDragEnterEvent:拖動進入事件
當拖動操作進入部件時,該事件被發送到部件,忽略該事件,將會導至后續的拖放事件不能被發送。 通常在該部件上光標會在外觀上顯示為禁用的圖形。
QDragMoveEvnet:拖動移動事件
當拖動操作正在進行時,以及當具有焦點時按下鍵盤的修飾鍵(比如 Ctrl)時, 發送該事件, 要使部件能接收到該事件,則該部件必須接受 QDragEnterEvent 事件。
QDropEvent:放下事件
在完成拖放操作時發送該事件,即當用戶在部件上放下一個對象時,發送此事件。要使部件能接收到該事件,則該部件必須接受 QDragEnterEvent事件,且不能忽略 QDragMoveEvnt 事件。
QLeaveEvent:當拖放操作離開部件時發送該事件
注意:要使部件能接收到該事件,必須要使拖動先進入該部件(即產生 QDragEnterEvent 事件),然后再離開該部件,才會產生 QLeaveEvent 事件。因很少使用該事件,因此本文不做重點介紹。
上文中提到的必須接受是指必須重新實現該事件的處理函數并接受該事件,不能忽略是指在處件事理函數中不明確調用 ignore()函數忽略該事件,這意味著可以不必重新實現該事件的處理函數。
以上事件產生的順序為: QDragEnterEvent、 QDragMoveEvnet、 QDropEvent
1.4 編寫拖放程序的步驟
在需要接受放下數據的部件上調用 QWidget::setAcceptDrops()函數以使該部件能接受拖放事件。
啟動拖放: 通常在 mousePressEvent()或 mouseMoveEvent()函數中啟動拖放,記住啟動拖放就是調用 QDrag 對象的 exec()函數,因此也可以在 keyPressEvent()等函數中啟動拖放(因很少這樣做,所以本文不介紹這種情況下的拖放)。 在此步把需要拖動的數據保存在 QMimeData 對象中。
重新實現需要接受放下數據的部件的 dragEnterEvent()事件處理函數。
根據需要重新實現 dragMoveEvent 或 dropEvent()函數
1.5 簡單的拖放示例代碼
本示例程序示范了如何把數據從按鈕A拖至按鈕B:
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
from PyQt5.QtCore import QMimeData, qDebug
from PyQt5 import QtGui
from PyQt5.QtGui import QDrag
import sys
???????class MyButton(QPushButton):
def __init__(self, text:str) -> None:
super().__init__(text)
def mousePressEvent(self, e: QtGui.QMouseEvent) -> None:
'''
在該事件中啟動拖放
'''
# 將需要拖動的數據放入QMimeData對象中,該對象用于保存需要傳遞的數據
# 數據的內容完全由程序員自行設定。通常為界面上所選擇的內容。
my_mime_data = QMimeData()
# 這是QMimeData中存儲的內容,即拖放的數據
my_mime_data.setText(self.text())
# 設置拖動的數據,該函數會獲得QMimeData的所有權
my_drag = QDrag(self)
my_drag.setMimeData(my_mime_data)
# 啟動拖放
my_drag.exec_()
def dragEnterEvent(self, e: QtGui.QDragEnterEvent) -> None:
'''
處理是否接受拖動事件
'''
# 接受拖動進入事件
e.accept()
# 若忽略該事件,則不會再發送之后的事件,拖放至此結束,這會導致鼠標光標顯示為禁用的圖形
# e.ignore()
def dropEvent(self, e: QtGui.QDropEvent) -> None:
'''
處理拖動的數據(當然了,也可以不做任何處理)
'''
# 設置此部件的文本為拖動對象中的文本
self.setText(e.mimeData().text())
# 此事件不影響后續事件,可接受也可忽略
# e.accept()
# e.ignore()
class MyWidget(QWidget):
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.__init_ui()
def __init_ui(self):
btn_a = MyButton('AAA')
btn_b = MyButton('BBB')
btn_a.setAcceptDrops(False)
btn_b.setAcceptDrops(True)
layout = QHBoxLayout()
layout.addWidget(btn_a)
layout.addWidget(btn_b)
self.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
my_widget = MyWidget()
my_widget.show()
sys.exit(app.exec_())
運行效果如下:
原始狀態:
在按鈕AAA上按下鼠標左鍵不動并拖動到圖示位置,由于主窗口不接受放下事件,因此光標顯示為禁用的狀態
拖動AAA到按鈕BBB上時,會發送QDragEnterEvent事件,同時光標改變形狀,表示BBB按鈕可以接受拖動的數據,
在按鈕BBB上釋放鼠標時,此時發送QDropEvent事件,按鈕BBB的文本被修改為拖動對象中保存的數據。
至此,拖動結束。
原文鏈接:https://blog.csdn.net/hubing_hust/article/details/128072839
相關推薦
- 2022-08-15 springboot切換為redis緩存
- 2022-03-12 Nginx熱部署的實現_nginx
- 2022-11-13 C++實現RSA加密解密算法是示例代碼_C 語言
- 2023-01-07 Flutter基于Dart?Unwrapping?Multiple?Optional小技巧_Andr
- 2022-09-09 C++代碼和可執行程序在x86和arm上的區別介紹_C 語言
- 2022-04-03 Python?Flask?+?Redis?程序練習_python
- 2023-04-20 Error in render: “TypeError: data.slice is not a f
- 2023-01-23 Python操作MongoDB增刪改查代碼示例_python
- 最近更新
-
- 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同步修改后的遠程分支