python3+PyQt5重新实现自定义数据拖放处理


Posted in Python onApril 19, 2018

本文分成两部分,第一部分通过python3+PyQt5实现自定义数据的拖放操作。第二部分则对第一部分的程序进行修改,增加拖放操作时,菜单提示是否移动或拷贝,还有可以通过ctrl键盘来设置移动过程中拷贝源而非会将源删除。

自定义数据MIME数据类型QMimeData,MIME是一种用于处理具有多个组成部分的自定义数据的标准化格式。MIME数据由一个数据类型和一个子类型构成?例如,text/plain,text/html,image/png,要处理自定义MIME数据,就必须要选用一种自定义数据类型和一种子类型,然后将数据封装到QMimeData对象中。本例子中,我们创建端为application/x-icon-and-text类型的新MIME数据。

注:

dragEnterEvent这是一个拖拽事件的函数,我们把文件拖拽进程序界面打开,之前必须setAcceptDrops(true)了以后拖拽,但是只设置acceptDrops还不够,还需要在dragEnterEvent事件中对拖入的对象进行筛选,判断mimeData的类型是否是你能处理的,如果是,则调用event.acceptProposedAction()放行。拖放结束后会产生dropEvent事件,在那里进行最后的放置操作。总之这是拖拽事件函数的一个筛选事件并放置的函数。

第一部分:

#!/usr/bin/env python3
import os
import sys
from PyQt5.QtCore import (QByteArray, QDataStream, QIODevice, QMimeData,
  QPoint, QSize, Qt)
from PyQt5.QtWidgets import (QApplication, QDialog,QGridLayout,
        QLineEdit, QListWidget,QListWidgetItem, QWidget)
from PyQt5.QtGui import QIcon,QColor,QPainter,QFontMetricsF,QDrag

class DropLineEdit(QLineEdit):

 def __init__(self, parent=None):
  super(DropLineEdit, self).__init__(parent)
  self.setAcceptDrops(True)


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.setDropAction(Qt.CopyAction)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   text = ""
   #stream >> text
   text=stream.readQString()
   self.setText(text)
   event.setDropAction(Qt.CopyAction)
   event.accept()
  else:
   event.ignore()


class DnDListWidget(QListWidget):

 def __init__(self, parent=None):
  super(DnDListWidget, self).__init__(parent)
  self.setAcceptDrops(True)
  self.setDragEnabled(True)


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.setDropAction(Qt.MoveAction)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   text = ""
   icon = QIcon()
   #stream >> text >> icon
   text=stream.readQString()
   stream >> icon
   item = QListWidgetItem(text, self)
   item.setIcon(icon)
   event.setDropAction(Qt.MoveAction)
   event.accept()
  else:
   event.ignore()


 def startDrag(self, dropActions):
  item = self.currentItem()
  icon = item.icon()
  data = QByteArray()
  stream = QDataStream(data, QIODevice.WriteOnly)
  #stream << item.text() << icon
  stream.writeQString(item.text())
  stream << icon
  mimeData = QMimeData()
  mimeData.setData("application/x-icon-and-text", data)
  drag = QDrag(self)
  drag.setMimeData(mimeData)
  pixmap = icon.pixmap(24, 24)
  drag.setHotSpot(QPoint(12, 12))
  drag.setPixmap(pixmap)
  if drag.exec(Qt.MoveAction) == Qt.MoveAction:
   self.takeItem(self.row(item))


class DnDWidget(QWidget):

 def __init__(self, text, icon=QIcon(), parent=None):
  super(DnDWidget, self).__init__(parent)
  self.setAcceptDrops(True)
  self.text = text
  self.icon = icon


 def minimumSizeHint(self):
  fm = QFontMetricsF(self.font())
  if self.icon.isNull():
   return QSize(fm.width(self.text), fm.height() * 1.5)
  return QSize(34 + fm.width(self.text), max(34, fm.height() * 1.5))


 def paintEvent(self, event):
  height = QFontMetricsF(self.font()).height()
  painter = QPainter(self)
  painter.setRenderHint(QPainter.Antialiasing)
  painter.setRenderHint(QPainter.TextAntialiasing)
  painter.fillRect(self.rect(), QColor(Qt.yellow).lighter())
  if self.icon.isNull():
   painter.drawText(10, height, self.text)
  else:
   pixmap = self.icon.pixmap(24, 24)
   painter.drawPixmap(0, 5, pixmap)
   painter.drawText(34, height,
        self.text + " (Drag to or from me!)")


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.setDropAction(Qt.CopyAction)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   self.text = ""
   self.icon = QIcon()
   #stream >> self.text >> self.icon
   self.text=stream.readQString()
   stream>>self.icon

   event.setDropAction(Qt.CopyAction)
   event.accept()
   self.updateGeometry()
   self.update()
  else:
   event.ignore()


 def mouseMoveEvent(self, event):
  self.startDrag()
  QWidget.mouseMoveEvent(self, event)


 def startDrag(self):
  icon = self.icon
  if icon.isNull():
   return
  data = QByteArray()
  stream = QDataStream(data, QIODevice.WriteOnly)
  #stream << self.text << icon
  stream.writeQString(self.text)
  stream<<icon
  mimeData = QMimeData()
  mimeData.setData("application/x-icon-and-text", data)
  drag = QDrag(self)
  drag.setMimeData(mimeData)
  pixmap = icon.pixmap(24, 24)
  drag.setHotSpot(QPoint(12, 12))
  drag.setPixmap(pixmap)
  drag.exec(Qt.CopyAction)


class Form(QDialog):

 def __init__(self, parent=None):
  super(Form, self).__init__(parent)

  dndListWidget = DnDListWidget()
  path = os.path.dirname(__file__)
  for image in sorted(os.listdir(os.path.join(path, "images"))):
   if image.endswith(".png"):
    item = QListWidgetItem(image.split(".")[0].capitalize())
    item.setIcon(QIcon(os.path.join(path,
         "images/{0}".format(image))))
    dndListWidget.addItem(item)
  dndIconListWidget = DnDListWidget()
  dndIconListWidget.setViewMode(QListWidget.IconMode)
  dndWidget = DnDWidget("Drag to me!")
  dropLineEdit = DropLineEdit()

  layout = QGridLayout()
  layout.addWidget(dndListWidget, 0, 0)
  layout.addWidget(dndIconListWidget, 0, 1)
  layout.addWidget(dndWidget, 1, 0)
  layout.addWidget(dropLineEdit, 1, 1)
  self.setLayout(layout)

  self.setWindowTitle("Custom Drag and Drop")

if __name__ == "__main__":
 app = QApplication(sys.argv)
 form = Form()
 form.show()
 app.exec_()

运行结果:

python3+PyQt5重新实现自定义数据拖放处理

第二部分:

#!/usr/bin/env python3
import os
import sys
from PyQt5.QtCore import (QByteArray, QDataStream, QIODevice, QMimeData,
  QPoint, QSize, Qt)
from PyQt5.QtWidgets import (QApplication, QDialog,QGridLayout,
        QLineEdit, QListWidget,QListWidgetItem, QWidget,QMenu)
from PyQt5.QtGui import QIcon,QColor,QPainter,QFontMetricsF,QDrag,QCursor

class DropLineEdit(QLineEdit):

 def __init__(self, parent=None):
  super(DropLineEdit, self).__init__(parent)
  self.setAcceptDrops(True)


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.setDropAction(Qt.CopyAction)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   text = ""
   text=stream.readQString()
   self.setText(text)
   event.setDropAction(Qt.CopyAction)
   event.accept()
  else:
   event.ignore()


class DnDMenuListWidget(QListWidget):

 def __init__(self, parent=None):
  super(DnDMenuListWidget, self).__init__(parent)
  self.setAcceptDrops(True)
  self.setDragEnabled(True)
  self.dropAction = Qt.CopyAction


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.setDropAction(Qt.MoveAction)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   text = ""
   icon = QIcon()
   text=stream.readQString()
   stream>>icon
   menu = QMenu(self)
   menu.addAction("&Copy", self.setCopyAction)
   menu.addAction("&Move", self.setMoveAction)
   if menu.exec_(QCursor.pos()):
    item = QListWidgetItem(text, self)
    item.setIcon(icon)
    event.setDropAction(self.dropAction)
    event.accept()
    return
   else:
    event.setDropAction(Qt.IgnoreAction)
  event.ignore()


 def setCopyAction(self):
  self.dropAction = Qt.CopyAction


 def setMoveAction(self):
  self.dropAction = Qt.MoveAction


 def startDrag(self, dropActions):
  item = self.currentItem()
  icon = item.icon()
  data = QByteArray()
  stream = QDataStream(data, QIODevice.WriteOnly)
  stream.writeQString(item.text())
  stream<<icon
  mimeData = QMimeData()
  mimeData.setData("application/x-icon-and-text", data)
  drag = QDrag(self)
  drag.setMimeData(mimeData)
  pixmap = icon.pixmap(24, 24)
  drag.setHotSpot(QPoint(12, 12))
  drag.setPixmap(pixmap)
  if (drag.exec(Qt.MoveAction|Qt.CopyAction) == Qt.MoveAction):
   self.takeItem(self.row(item))


class DnDCtrlListWidget(QListWidget):

 def __init__(self, parent=None):
  super(DnDCtrlListWidget, self).__init__(parent)
  self.setAcceptDrops(True)
  self.setDragEnabled(True)


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   action = Qt.MoveAction
   if event.keyboardModifiers() & Qt.ControlModifier:
    action = Qt.CopyAction
   event.setDropAction(action)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   text = ""
   icon = QIcon()
   text=stream.readQString()
   stream>>icon
   item = QListWidgetItem(text, self)
   item.setIcon(icon)
   action = Qt.MoveAction
   if event.keyboardModifiers() & Qt.ControlModifier:
    action = Qt.CopyAction
   event.setDropAction(action)
   event.accept()
  else:
   event.ignore()


 def startDrag(self, dropActions):
  item = self.currentItem()
  icon = item.icon()
  data = QByteArray()
  stream = QDataStream(data, QIODevice.WriteOnly)
  stream.writeQString(item.text())
  stream<<icon
  mimeData = QMimeData()
  mimeData.setData("application/x-icon-and-text", data)
  drag = QDrag(self)
  drag.setMimeData(mimeData)
  pixmap = icon.pixmap(24, 24)
  drag.setHotSpot(QPoint(12, 12))
  drag.setPixmap(pixmap)
  if (drag.exec(Qt.MoveAction|Qt.CopyAction) == Qt.MoveAction):
   self.takeItem(self.row(item))


class DnDWidget(QWidget):

 def __init__(self, text, icon=QIcon(), parent=None):
  super(DnDWidget, self).__init__(parent)
  self.setAcceptDrops(True)
  self.text = text
  self.icon = icon


 def minimumSizeHint(self):
  fm = QFontMetricsF(self.font())
  if self.icon.isNull():
   return QSize(fm.width(self.text), fm.height() * 1.5)
  return QSize(34 + fm.width(self.text), max(34, fm.height() * 1.5))


 def paintEvent(self, event):
  height = QFontMetricsF(self.font()).height()
  painter = QPainter(self)
  painter.setRenderHint(QPainter.Antialiasing)
  painter.setRenderHint(QPainter.TextAntialiasing)
  painter.fillRect(self.rect(), QColor(Qt.yellow).lighter())
  if self.icon.isNull():
   painter.drawText(10, height, self.text)
  else:
   pixmap = self.icon.pixmap(24, 24)
   painter.drawPixmap(0, 5, pixmap)
   painter.drawText(34, height,
        self.text + " (Drag to or from me!)")


 def dragEnterEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.accept()
  else:
   event.ignore()


 def dragMoveEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   event.setDropAction(Qt.CopyAction)
   event.accept()
  else:
   event.ignore()


 def dropEvent(self, event):
  if event.mimeData().hasFormat("application/x-icon-and-text"):
   data = event.mimeData().data("application/x-icon-and-text")
   stream = QDataStream(data, QIODevice.ReadOnly)
   self.text = ""
   self.icon = QIcon()
   self.text=stream.readQString()
   stream>>self.icon

   event.setDropAction(Qt.CopyAction)
   event.accept()
   self.updateGeometry()
   self.update()
  else:
   event.ignore()


 def mouseMoveEvent(self, event):
  self.startDrag()
  QWidget.mouseMoveEvent(self, event)


 def startDrag(self):
  icon = self.icon
  if icon.isNull():
   return
  data = QByteArray()
  stream = QDataStream(data, QIODevice.WriteOnly)
  stream.writeQString(self.text)
  stream<<icon
  mimeData = QMimeData()
  mimeData.setData("application/x-icon-and-text", data)
  drag = QDrag(self)
  drag.setMimeData(mimeData)
  pixmap = icon.pixmap(24, 24)
  drag.setHotSpot(QPoint(12, 12))
  drag.setPixmap(pixmap)
  drag.exec(Qt.CopyAction)


class Form(QDialog):

 def __init__(self, parent=None):
  super(Form, self).__init__(parent)

  dndListWidget = DnDMenuListWidget()
  path = os.path.dirname(__file__)
  for image in sorted(os.listdir(os.path.join(path, "images"))):
   if image.endswith(".png"):
    item = QListWidgetItem(image.split(".")[0].capitalize())
    item.setIcon(QIcon(os.path.join(path,
         "images/{0}".format(image))))
    dndListWidget.addItem(item)
  dndIconListWidget = DnDCtrlListWidget()
  dndIconListWidget.setViewMode(QListWidget.IconMode)
  dndWidget = DnDWidget("Drag to me!")
  dropLineEdit = DropLineEdit()

  layout = QGridLayout()
  layout.addWidget(dndListWidget, 0, 0)
  layout.addWidget(dndIconListWidget, 0, 1)
  layout.addWidget(dndWidget, 1, 0)
  layout.addWidget(dropLineEdit, 1, 1)
  self.setLayout(layout)

  self.setWindowTitle("Custom Drag and Drop")

if __name__ == "__main__":
 app = QApplication(sys.argv)
 form = Form()
 form.show()
 app.exec_()

运行结果:

python3+PyQt5重新实现自定义数据拖放处理

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中设置变量作为默认值时容易遇到的错误
Apr 03 Python
python生成器generator用法实例分析
Jun 04 Python
windows10系统中安装python3.x+scrapy教程
Nov 08 Python
Python的时间模块datetime详解
Apr 17 Python
Python3.6 Schedule模块定时任务(实例讲解)
Nov 09 Python
CentOS 6.5中安装Python 3.6.2的方法步骤
Dec 03 Python
详解Python核心对象类型字符串
Feb 11 Python
Python删除n行后的其他行方法
Jan 28 Python
Python爬虫实现爬取百度百科词条功能实例
Apr 05 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
Dec 04 Python
Python如何使用paramiko模块连接linux
Mar 18 Python
Python 列表推导式需要注意的地方
Oct 23 Python
python之从文件读取数据到list的实例讲解
Apr 19 #Python
python实现读取大文件并逐行写入另外一个文件
Apr 19 #Python
python按行读取文件,去掉每行的换行符\n的实例
Apr 19 #Python
PyQt5每天必学之拖放事件
Aug 27 #Python
sublime python3 输入换行不结束的方法
Apr 19 #Python
PyQt5每天必学之像素图控件QPixmap
Apr 19 #Python
PyQt5每天必学之单行文本框
Apr 19 #Python
You might like
PHP设置一边执行一边输出结果的代码
2013/09/30 PHP
php登录超时检测功能实例详解
2017/03/21 PHP
PHP回调函数与匿名函数实例详解
2017/08/16 PHP
用showModalDialog弹出页面后,提交表单总是弹出一个新窗口
2009/07/18 Javascript
jQuery+slidereveal实现的面板滑动侧边展出效果
2015/03/14 Javascript
js滑动提示效果代码分享
2016/03/10 Javascript
浅析jQuery Ajax通用js封装
2016/06/22 Javascript
微信小程序 swiper组件详解及实例代码
2016/10/25 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
原生js实现验证码功能
2017/03/16 Javascript
解决OneThink中无法异步提交kindeditor文本框中修改后的内容方法
2017/05/05 Javascript
JS实现图片居中悬浮效果
2017/12/25 Javascript
小程序实现展开/收起的效果示例
2018/09/22 Javascript
VUE项目中加载已保存的笔记实例方法
2019/09/14 Javascript
WEEX环境搭建与入门详解
2019/10/16 Javascript
vue与iframe之间的信息交互的实现
2020/04/08 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
2020/04/10 Javascript
Vue3.0的优化总结
2020/10/16 Javascript
Vue Elenent实现表格相同数据列合并
2020/11/30 Vue.js
[00:27]DOTA2次级职业联赛 - Lilith战队宣传片
2014/12/01 DOTA
Python写入CSV文件的方法
2015/07/08 Python
python的concat等多种用法详解
2018/11/28 Python
Python简单基础小程序的实例代码
2019/04/28 Python
深入浅析Python 中 is 语法带来的误解
2019/05/07 Python
Python实现Mysql数据统计及numpy统计函数
2019/07/15 Python
Python基于正则表达式实现计算器功能
2020/07/13 Python
如何在Python3中使用telnetlib模块连接网络设备
2020/09/21 Python
使用Python爬取Json数据的示例代码
2020/12/07 Python
CSS3 2D模拟实现摩天轮旋转效果
2016/11/16 HTML / CSS
CSS 说明横向进度条最后显示文字的实现代码
2020/11/10 HTML / CSS
html5文本内容_动力节点Java学院整理
2017/07/11 HTML / CSS
《云雀的心愿》教学反思
2014/02/25 职场文书
乡镇消防工作实施方案
2014/03/27 职场文书
《谁的本领大》教后反思
2014/04/25 职场文书
诉讼财产保全担保书
2014/05/20 职场文书
2014卖家双十一活动策划书
2014/09/29 职场文书