PyQt5使用mimeData實現(xiàn)拖拽事件教程示例解析下
系列文章:
PyQt5使用mimeData實現(xiàn)拖拽事件教程示例解析上
實現(xiàn)思路
1、簡要介紹QMimeData
2、QMimeData的用例1:在QT實現(xiàn)外部文件拖拽并展示
3、QMimeData的用例2:兩個QListWidget之間的item交換
兩個用例的實現(xiàn)效果如下:
1、簡要介紹QMimeData
關于拖拽事件與QMimeData的一些關系,在第一篇文章中已經(jīng)說明清楚了,這篇文章主要是往QMimeData中存放一些數(shù)據(jù),以供拖動及放置的時候做判斷(及數(shù)據(jù)通過QMimeData傳遞)
在第一個例子中: 由于文件的拖拽本身就存放了一些信息,因此我們并沒有如第一篇文章那樣創(chuàng)建一個QDrag,并且創(chuàng)建一個QMimeData
在第二個例子中: 我們此時給mimeData設置了一個text值,用于之后交換ItemList
2、QMimeData的用例1
在QT實現(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"): # 關于這個函數(shù)和accept的區(qū)別在下面會展示 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_()
上述代碼可以將外部的文件拖進來并進行展示,其中有幾個要點要注意一下:
1、我們并沒有創(chuàng)建QDrag事件,因為拖拽的起始并非在該窗口及窗口內(nèi)的Widget中,而是從外部直接拖拽進來,這類事件本身已經(jīng)有QDrag了
2、我們利用QMimeData中攜帶的信息判斷進入的拖拽事件是否為我們所需要的,即event.mimeData().hasFormat(“text/uri-list”), 關于里面的類型,可以自行查找該網(wǎng)站Media Types
3、上面我們沒有使用 event.accept 而是使用 acceptProposedAction 的原因如下圖
4、拖放結(jié)束后,我們將文件讀取進來并進行展示
3、QMimeData的用例2
兩個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_()
簡要說明一下上面的實現(xiàn)過程:
1、我們在一個QWidget里面放置了兩個QListWidget,并實現(xiàn)QListWidget之間item的交換
2、QListWidget中在mouseMoveEvent中創(chuàng)建了QDrag,并且我們創(chuàng)建一個QMimeData, 并在其存儲當前選中item的text ,此處我們還設置了拖拽時候的圖標樣式(上面gif的是沒有調(diào)整過大小的,實際效果可以把代碼拿去自己運行一下)
3、在dragMoveEvent中判斷是否為同源事件,非同源則將當前的拖拽設置為Qt.MoveAction
4、在dragEnterEvent中接收符合條件的拖拽事件
5、在dropEvent中,從QMimeData中獲取最初設置的text值,并添加到當前的QListWidget,要注意的是,這里的self并非最初QDrag產(chǎn)生信號的self,兩個self在這里其實代表的分別是兩個窗口
6、在上一篇文章中 說過,exec方法是阻塞方法 ,因此在整個拖拽事件運行完之后,又會回到下面這段代碼中,把后面的方法執(zhí)行完,此時我們刪去自身被拖動的item
if drag.exec(Qt.MoveAction) == Qt.MoveAction: self.removeSel()
以上就是PyQt5使用mimeData實現(xiàn)拖拽事件教程示例解析下的詳細內(nèi)容,更多關于PyQt5拖拽事件mimeData使用的資料請關注腳本之家其它相關文章!
相關文章
pycharm2022.2遠程連接服務器調(diào)試代碼實現(xiàn)
本文主要介紹了pycharm2022.2遠程連接服務器調(diào)試代碼實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-02-02python-docx修改已存在的Word文檔的表格的字體格式方法
今天小編就為大家分享一篇python-docx修改已存在的Word文檔的表格的字體格式方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05python通過函數(shù)名調(diào)用函數(shù)的幾種方法總結(jié)
今天帶大家學習的是怎么使用python通過函數(shù)名調(diào)用函數(shù),文中對python通過函數(shù)名調(diào)用函數(shù)的幾種方法有非常詳細的介紹,需要的朋友可以參考下2021-06-06Python操作SQLite/MySQL/LMDB數(shù)據(jù)庫的方法
這篇文章主要介紹了Python操作SQLite/MySQL/LMDB數(shù)據(jù)庫的方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11