PyQt5使用mimeData實(shí)現(xiàn)拖拽事件教程示例解析下
系列文章:
PyQt5使用mimeData實(shí)現(xiàn)拖拽事件教程示例解析上
實(shí)現(xiàn)思路
1、簡(jiǎn)要介紹QMimeData
2、QMimeData的用例1:在QT實(shí)現(xiàn)外部文件拖拽并展示
3、QMimeData的用例2:兩個(gè)QListWidget之間的item交換
兩個(gè)用例的實(shí)現(xiàn)效果如下:


1、簡(jiǎn)要介紹QMimeData
關(guān)于拖拽事件與QMimeData的一些關(guān)系,在第一篇文章中已經(jīng)說(shuō)明清楚了,這篇文章主要是往QMimeData中存放一些數(shù)據(jù),以供拖動(dòng)及放置的時(shí)候做判斷(及數(shù)據(jù)通過(guò)QMimeData傳遞)
在第一個(gè)例子中: 由于文件的拖拽本身就存放了一些信息,因此我們并沒(méi)有如第一篇文章那樣創(chuàng)建一個(gè)QDrag,并且創(chuàng)建一個(gè)QMimeData
在第二個(gè)例子中: 我們此時(shí)給mimeData設(shè)置了一個(gè)text值,用于之后交換ItemList
2、QMimeData的用例1
在QT實(shí)現(xiàn)外部文件拖拽并展示
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit
from PyQt5.QtCore import QIODevice, QFile
class ComplexDrag(QMainWindow):
def __init__(self):
super(ComplexDrag, self).__init__()
self.setAcceptDrops(True)
self.textEditor = None
self.initUI()
def initUI(self):
self.textEditor = QTextEdit()
self.setCentralWidget(self.textEditor)
self.textEditor.setAcceptDrops(False)
self.setAcceptDrops(True)
self.setWindowTitle("拖拽")
def dragEnterEvent(self, event):
if event.mimeData().hasFormat("text/uri-list"):
# 關(guān)于這個(gè)函數(shù)和accept的區(qū)別在下面會(huì)展示
event.acceptProposedAction()
def dropEvent(self, event):
urls = event.mimeData().urls()
if urls == "":
return
fileName = urls.pop().toLocalFile()
if fileName == "":
return
if self.readFile(fileName):
self.setWindowTitle("Drag File Success")
def readFile(self, fileName):
r = False
file = QFile(fileName)
content = ""
if file.open(QIODevice.ReadOnly):
content = file.readAll()
r = True
self.textEditor.setText(str(content, "utf-8"))
return r
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = ComplexDrag()
ex.show()
app.exec_()
上述代碼可以將外部的文件拖進(jìn)來(lái)并進(jìn)行展示,其中有幾個(gè)要點(diǎn)要注意一下:
1、我們并沒(méi)有創(chuàng)建QDrag事件,因?yàn)橥献У钠鹗疾⒎窃谠摯翱诩按翱趦?nèi)的Widget中,而是從外部直接拖拽進(jìn)來(lái),這類事件本身已經(jīng)有QDrag了
2、我們利用QMimeData中攜帶的信息判斷進(jìn)入的拖拽事件是否為我們所需要的,即event.mimeData().hasFormat(“text/uri-list”), 關(guān)于里面的類型,可以自行查找該網(wǎng)站Media Types
3、上面我們沒(méi)有使用 event.accept 而是使用 acceptProposedAction 的原因如下圖

4、拖放結(jié)束后,我們將文件讀取進(jìn)來(lái)并進(jìn)行展示
3、QMimeData的用例2
兩個(gè)QListWidget之間的item交換
# -*- coding: utf-8 -*-
import sys
from threading import Event
from PyQt5.QtGui import QDrag, QPixmap
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QListWidget, QDialog
from PyQt5.QtCore import QMimeData, Qt
class MainWindow(QDialog):
def __init__(self):
super(MainWindow, self).__init__()
self.projectA = ComplexDrag(self)
self.projectB = ComplexDrag(self)
self.projectA.addItem("Giosue Carducci")
self.projectA.addItem("Eyvind Johnson")
self.projectA.addItem("Sally Prudhomme")
self.projectA.addItem("Henryk Sienkiewicz")
self.projectA.addItem("Carl Spitteler")
self.projectA.addItem("Rabindranath Tagore")
self.projectA.addItem("Kawabata Yasunari")
self.projectB.addItem("Rudolf Eucken")
self.projectB.addItem("Anatole France")
self.projectB.addItem("Rudyard Kipling")
self.projectB.addItem("Thomas Mann")
self.projectB.addItem("Eugene O'Neill")
self.projectB.addItem("Sigrid Undset")
lay = QHBoxLayout()
lay.addWidget(self.projectA)
lay.addWidget(self.projectB)
self.setLayout(lay)
class ComplexDrag(QListWidget):
onDropEvent = Event()
def __init__(self, parent=None):
super(ComplexDrag, self).__init__(parent)
self.setAcceptDrops(True)
self.startPos = None
def removeSel(self):
listItems = self.selectedItems()
if not listItems:
return
for item in listItems:
self.takeItem(self.row(item))
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.startPos = event.pos()
super(ComplexDrag, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
distance = (event.pos() - self.startPos).manhattanLength()
if distance >= QApplication.startDragDistance():
item = self.currentItem()
if item:
mimeData = QMimeData()
mimeData.setText(item.text())
drag = QDrag(self)
drag.setMimeData(mimeData)
pixmap = QPixmap("computer.svg").scaled(20, 20, Qt.KeepAspectRatio)
drag.setPixmap(pixmap)
self.removeItemWidget(item)
if drag.exec(Qt.MoveAction) == Qt.MoveAction:
self.removeSel()
super(ComplexDrag, self).mouseMoveEvent(event)
def dragMoveEvent(self, event):
source = event.source()
if source and source != self:
event.setDropAction(Qt.MoveAction)
def dragEnterEvent(self, event):
source = event.source()
if source and source != self:
event.setDropAction(Qt.MoveAction)
event.accept()
def dropEvent(self, event):
source = event.source()
if source and source != self:
self.addItem(event.mimeData().text())
event.setDropAction(Qt.MoveAction)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
ex.show()
app.exec_()
簡(jiǎn)要說(shuō)明一下上面的實(shí)現(xiàn)過(guò)程:
1、我們?cè)谝粋€(gè)QWidget里面放置了兩個(gè)QListWidget,并實(shí)現(xiàn)QListWidget之間item的交換
2、QListWidget中在mouseMoveEvent中創(chuàng)建了QDrag,并且我們創(chuàng)建一個(gè)QMimeData, 并在其存儲(chǔ)當(dāng)前選中item的text ,此處我們還設(shè)置了拖拽時(shí)候的圖標(biāo)樣式(上面gif的是沒(méi)有調(diào)整過(guò)大小的,實(shí)際效果可以把代碼拿去自己運(yùn)行一下)
3、在dragMoveEvent中判斷是否為同源事件,非同源則將當(dāng)前的拖拽設(shè)置為Qt.MoveAction
4、在dragEnterEvent中接收符合條件的拖拽事件
5、在dropEvent中,從QMimeData中獲取最初設(shè)置的text值,并添加到當(dāng)前的QListWidget,要注意的是,這里的self并非最初QDrag產(chǎn)生信號(hào)的self,兩個(gè)self在這里其實(shí)代表的分別是兩個(gè)窗口
6、在上一篇文章中 說(shuō)過(guò),exec方法是阻塞方法 ,因此在整個(gè)拖拽事件運(yùn)行完之后,又會(huì)回到下面這段代碼中,把后面的方法執(zhí)行完,此時(shí)我們刪去自身被拖動(dòng)的item
if drag.exec(Qt.MoveAction) == Qt.MoveAction: self.removeSel()
以上就是PyQt5使用mimeData實(shí)現(xiàn)拖拽事件教程示例解析下的詳細(xì)內(nèi)容,更多關(guān)于PyQt5拖拽事件mimeData使用的資料請(qǐng)關(guān)注本站其它相關(guān)文章!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信