新闻动态

PyQt5使用mimeData实现拖拽事件教程示例解析下

发布日期:2021-12-17 18:50 | 文章来源:源码之家

系列文章:
PyQt5使用mimeData实现拖拽事件教程示例解析上

实现思路

1、简要介绍QMimeData
2、QMimeData的用例1:在QT实现外部文件拖拽并展示
3、QMimeData的用例2:两个QListWidget之间的item交换
两个用例的实现效果如下:

1、简要介绍QMimeData

关于拖拽事件与QMimeData的一些关系,在第一篇文章中已经说明清楚了,这篇文章主要是往QMimeData中存放一些数据,以供拖动及放置的时候做判断(及数据通过QMimeData传递)
在第一个例子中: 由于文件的拖拽本身就存放了一些信息,因此我们并没有如第一篇文章那样创建一个QDrag,并且创建一个QMimeData
在第二个例子中: 我们此时给mimeData设置了一个text值,用于之后交换ItemList

2、QMimeData的用例1

在QT实现外部文件拖拽并展示

# -*- 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"):
  	# 关于这个函数和accept的区别在下面会展示
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、我们并没有创建QDrag事件,因为拖拽的起始并非在该窗口及窗口内的Widget中,而是从外部直接拖拽进来,这类事件本身已经有QDrag了

2、我们利用QMimeData中携带的信息判断进入的拖拽事件是否为我们所需要的,即event.mimeData().hasFormat(“text/uri-list”), 关于里面的类型,可以自行查找该网站Media Types

3、上面我们没有使用 event.accept 而是使用 acceptProposedAction 的原因如下图

4、拖放结束后,我们将文件读取进来并进行展示

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_()

简要说明一下上面的实现过程:
1、我们在一个QWidget里面放置了两个QListWidget,并实现QListWidget之间item的交换

2、QListWidget中在mouseMoveEvent中创建了QDrag,并且我们创建一个QMimeData, 并在其存储当前选中item的text ,此处我们还设置了拖拽时候的图标样式(上面gif的是没有调整过大小的,实际效果可以把代码拿去自己运行一下)

3、在dragMoveEvent中判断是否为同源事件,非同源则将当前的拖拽设置为Qt.MoveAction

4、在dragEnterEvent中接收符合条件的拖拽事件

5、在dropEvent中,从QMimeData中获取最初设置的text值,并添加到当前的QListWidget,要注意的是,这里的self并非最初QDrag产生信号的self,两个self在这里其实代表的分别是两个窗口

6、在上一篇文章中 说过,exec方法是阻塞方法 ,因此在整个拖拽事件运行完之后,又会回到下面这段代码中,把后面的方法执行完,此时我们删去自身被拖动的item

if drag.exec(Qt.MoveAction) == Qt.MoveAction:
self.removeSel()

以上就是PyQt5使用mimeData实现拖拽事件教程示例解析下的详细内容,更多关于PyQt5拖拽事件mimeData使用的资料请关注本站其它相关文章!

版权声明:本站文章来源标注为YINGSOO的内容版权均为本站所有,欢迎引用、转载,请保持原文完整并注明来源及原文链接。禁止复制或仿造本网站,禁止在非www.yingsoo.com所属的服务器上建立镜像,否则将依法追究法律责任。本站部分内容来源于网友推荐、互联网收集整理而来,仅供学习参考,不代表本站立场,如有内容涉嫌侵权,请联系alex-e#qq.com处理。

相关文章

实时开通

自选配置、实时开通

免备案

全球线路精选!

全天候客户服务

7x24全年不间断在线

专属顾问服务

1对1客户咨询顾问

在线
客服

在线客服:7*24小时在线

客服
热线

400-630-3752
7*24小时客服服务热线

关注
微信

关注官方微信
顶部