網(wǎng)站首頁 編程語言 正文
PyQt5的拖放
拖放涉及到的主要的一些類如下所示:
一、拖放的基本原理
1.1 拖放的動(dòng)作
拖放操作包括兩個(gè)動(dòng)作:
- 拖動(dòng)(drag)
- 放下(drop 或稱為放置)。
當(dāng)被拖動(dòng)時(shí)拖動(dòng)的數(shù)據(jù)會(huì)被存儲(chǔ)為 MIME 類型的對(duì)象, MIME 類型使用 QMimeData 類來描述。 MIME 類型通常由剪貼板和拖放系統(tǒng)使用,以識(shí)別不同類型的數(shù)據(jù)。
- 拖動(dòng)點(diǎn)(drag site):拖動(dòng)的起始位置。
- 放下點(diǎn)(drop site):被拖動(dòng)的對(duì)象放下的位置,若部件不能接受拖動(dòng)的對(duì)象, Qt 會(huì)改變光標(biāo)的形狀(一個(gè)禁用形狀)來向用戶進(jìn)行說明。
1.2 拖動(dòng)的啟動(dòng)和結(jié)束
啟動(dòng)拖放:
拖放通過調(diào)用 QDrag::exec()函數(shù)而啟動(dòng),該函數(shù)是一個(gè)阻塞函數(shù)(但不會(huì)阻塞主事件循環(huán)),這意味著在拖放操作結(jié)束之前,不會(huì)返回該函數(shù),調(diào)用 QDrag::exec()函數(shù)后, Qt 擁有對(duì)拖動(dòng)對(duì)象的所有權(quán),并會(huì)在必要時(shí)將其刪除。
結(jié)束拖放:
當(dāng)用戶放下拖動(dòng)或取消拖動(dòng)操作時(shí)結(jié)束拖放。
1.3 拖放產(chǎn)生的過程和事件
啟動(dòng)拖放后,會(huì)使數(shù)據(jù)被拖動(dòng),這時(shí)需要按住鼠標(biāo)按鍵才能拖動(dòng)需要拖動(dòng)的數(shù)據(jù),松開鼠標(biāo)按鍵時(shí)意味著拖動(dòng)結(jié)束。
默認(rèn)情況下,部件不接受放下事件。使用 QWidget::setAcceptDrops()函數(shù)可設(shè)置部件是否接受放下事件(即,拖放完成時(shí)發(fā)送的事件)。只有在部件接受放下事件的情形下,才會(huì)產(chǎn)生以下事件。
QDragEnterEvent:拖動(dòng)進(jìn)入事件
當(dāng)拖動(dòng)操作進(jìn)入部件時(shí),該事件被發(fā)送到部件,忽略該事件,將會(huì)導(dǎo)至后續(xù)的拖放事件不能被發(fā)送。 通常在該部件上光標(biāo)會(huì)在外觀上顯示為禁用的圖形。
QDragMoveEvnet:拖動(dòng)移動(dòng)事件
當(dāng)拖動(dòng)操作正在進(jìn)行時(shí),以及當(dāng)具有焦點(diǎn)時(shí)按下鍵盤的修飾鍵(比如 Ctrl)時(shí), 發(fā)送該事件, 要使部件能接收到該事件,則該部件必須接受 QDragEnterEvent 事件。
QDropEvent:放下事件
在完成拖放操作時(shí)發(fā)送該事件,即當(dāng)用戶在部件上放下一個(gè)對(duì)象時(shí),發(fā)送此事件。要使部件能接收到該事件,則該部件必須接受 QDragEnterEvent事件,且不能忽略 QDragMoveEvnt 事件。
QLeaveEvent:當(dāng)拖放操作離開部件時(shí)發(fā)送該事件
注意:要使部件能接收到該事件,必須要使拖動(dòng)先進(jìn)入該部件(即產(chǎn)生 QDragEnterEvent 事件),然后再離開該部件,才會(huì)產(chǎn)生 QLeaveEvent 事件。因很少使用該事件,因此本文不做重點(diǎn)介紹。
上文中提到的必須接受是指必須重新實(shí)現(xiàn)該事件的處理函數(shù)并接受該事件,不能忽略是指在處件事理函數(shù)中不明確調(diào)用 ignore()函數(shù)忽略該事件,這意味著可以不必重新實(shí)現(xiàn)該事件的處理函數(shù)。
以上事件產(chǎn)生的順序?yàn)椋?QDragEnterEvent、 QDragMoveEvnet、 QDropEvent
1.4 編寫拖放程序的步驟
在需要接受放下數(shù)據(jù)的部件上調(diào)用 QWidget::setAcceptDrops()函數(shù)以使該部件能接受拖放事件。
啟動(dòng)拖放: 通常在 mousePressEvent()或 mouseMoveEvent()函數(shù)中啟動(dòng)拖放,記住啟動(dòng)拖放就是調(diào)用 QDrag 對(duì)象的 exec()函數(shù),因此也可以在 keyPressEvent()等函數(shù)中啟動(dòng)拖放(因很少這樣做,所以本文不介紹這種情況下的拖放)。 在此步把需要拖動(dòng)的數(shù)據(jù)保存在 QMimeData 對(duì)象中。
重新實(shí)現(xiàn)需要接受放下數(shù)據(jù)的部件的 dragEnterEvent()事件處理函數(shù)。
根據(jù)需要重新實(shí)現(xiàn) dragMoveEvent 或 dropEvent()函數(shù)
1.5 簡(jiǎn)單的拖放示例代碼
本示例程序示范了如何把數(shù)據(jù)從按鈕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:
'''
在該事件中啟動(dòng)拖放
'''
# 將需要拖動(dòng)的數(shù)據(jù)放入QMimeData對(duì)象中,該對(duì)象用于保存需要傳遞的數(shù)據(jù)
# 數(shù)據(jù)的內(nèi)容完全由程序員自行設(shè)定。通常為界面上所選擇的內(nèi)容。
my_mime_data = QMimeData()
# 這是QMimeData中存儲(chǔ)的內(nèi)容,即拖放的數(shù)據(jù)
my_mime_data.setText(self.text())
# 設(shè)置拖動(dòng)的數(shù)據(jù),該函數(shù)會(huì)獲得QMimeData的所有權(quán)
my_drag = QDrag(self)
my_drag.setMimeData(my_mime_data)
# 啟動(dòng)拖放
my_drag.exec_()
def dragEnterEvent(self, e: QtGui.QDragEnterEvent) -> None:
'''
處理是否接受拖動(dòng)事件
'''
# 接受拖動(dòng)進(jìn)入事件
e.accept()
# 若忽略該事件,則不會(huì)再發(fā)送之后的事件,拖放至此結(jié)束,這會(huì)導(dǎo)致鼠標(biāo)光標(biāo)顯示為禁用的圖形
# e.ignore()
def dropEvent(self, e: QtGui.QDropEvent) -> None:
'''
處理拖動(dòng)的數(shù)據(jù)(當(dāng)然了,也可以不做任何處理)
'''
# 設(shè)置此部件的文本為拖動(dòng)對(duì)象中的文本
self.setText(e.mimeData().text())
# 此事件不影響后續(xù)事件,可接受也可忽略
# 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_())
運(yùn)行效果如下:
原始狀態(tài):
在按鈕AAA上按下鼠標(biāo)左鍵不動(dòng)并拖動(dòng)到圖示位置,由于主窗口不接受放下事件,因此光標(biāo)顯示為禁用的狀態(tài)
拖動(dòng)AAA到按鈕BBB上時(shí),會(huì)發(fā)送QDragEnterEvent事件,同時(shí)光標(biāo)改變形狀,表示BBB按鈕可以接受拖動(dòng)的數(shù)據(jù),
在按鈕BBB上釋放鼠標(biāo)時(shí),此時(shí)發(fā)送QDropEvent事件,按鈕BBB的文本被修改為拖動(dòng)對(duì)象中保存的數(shù)據(jù)。
至此,拖動(dòng)結(jié)束。
原文鏈接:https://blog.csdn.net/hubing_hust/article/details/128072839
相關(guān)推薦
- 2022-07-31 Python加密與解密模塊hashlib與hmac_python
- 2023-03-01 Golang?Makefile示例深入講解使用_Golang
- 2023-01-26 Redis的數(shù)據(jù)復(fù)制過程詳解_Redis
- 2022-07-11 go語言數(shù)據(jù)結(jié)構(gòu)之前綴樹Trie_Golang
- 2023-09-12 利用ImportBeanDefinitionRegistrar手動(dòng)向Spring容器注入Bean
- 2022-05-04 python直接調(diào)用和使用swig法方調(diào)用c++庫_python
- 2022-02-22 記一個(gè)nginx錯(cuò)誤directory index of “/var/www/xxxx/“ is f
- 2022-05-10 react設(shè)置多個(gè)classname
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支