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实现抓取百度搜索结果页的网站标题信息
Jan 22 Python
浅谈python socket函数中,send与sendall的区别与使用方法
May 09 Python
python奇偶行分开存储实现代码
Mar 19 Python
python中subprocess批量执行linux命令
Apr 27 Python
浅谈python中str字符串和unicode对象字符串的拼接问题
Dec 04 Python
Python使用pandas对数据进行差分运算的方法
Dec 22 Python
python函数与方法的区别总结
Jun 23 Python
Flask框架学习笔记之使用Flask实现表单开发详解
Aug 12 Python
pytorch 归一化与反归一化实例
Dec 31 Python
python控制台打印log输出重复的解决方法
May 14 Python
pytorch实现ResNet结构的实例代码
May 17 Python
pytorch 权重weight 与 梯度grad 可视化操作
Jun 05 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
ThinkPHP模板自定义标签使用方法
2014/06/26 PHP
php原生导出excel文件的两种方法(推荐)
2016/11/19 PHP
redis+php实现微博(一)注册与登录功能详解
2019/09/23 PHP
用YUI做了个标签浏览效果
2007/02/20 Javascript
基于JQuery的访问WebService的代码(可访问Java[Xfire])
2010/11/19 Javascript
javascript 正则表达式相关应介绍
2012/11/27 Javascript
IE的fireEvent方法概述及应用
2013/02/22 Javascript
js创建对象的区别示例介绍
2014/07/24 Javascript
JS+CSS实现仿新浪微博搜索框的方法
2015/02/24 Javascript
jQuery选择器源码解读(七):elementMatcher函数
2015/03/31 Javascript
JavaScript判断数组是否包含指定元素的方法
2015/07/01 Javascript
微信小程序page的生命周期和音频播放及监听实例详解
2017/04/07 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
2017/05/01 jQuery
十个免费的web前端开发工具详细整理
2017/09/18 Javascript
浅析node应用的timing-attack安全漏洞
2018/02/28 Javascript
webpack中如何使用雪碧图的示例代码
2018/11/11 Javascript
创建echart多个联动的示例代码
2018/11/23 Javascript
node.js 基于cheerio的爬虫工具的实现(需要登录权限的爬虫工具)
2019/04/10 Javascript
jQuery AJAX应用实例总结
2020/05/19 jQuery
原生JS实现微信通讯录
2020/06/18 Javascript
Python获取电脑硬件信息及状态的实现方法
2014/08/29 Python
Python登录系统界面实现详解
2019/06/25 Python
使用Python+selenium实现第一个自动化测试脚本
2020/03/17 Python
python中random.randint和random.randrange的区别详解
2020/09/20 Python
使用Python获取爱奇艺电视剧弹幕数据的示例代码
2021/01/12 Python
英国最大的香水商店:The Fragrance Shop
2018/07/06 全球购物
GANT葡萄牙官方商店:拥有美国运动服传统的生活方式品牌
2018/10/18 全球购物
餐饮总经理岗位职责
2014/03/07 职场文书
4S店售后客服自我评价
2014/04/09 职场文书
工厂门卫的岗位职责
2014/07/27 职场文书
研究生导师评语
2014/12/31 职场文书
小学母亲节活动总结
2015/02/10 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis
Mysql中where与on的区别及何时使用详析
2021/08/04 MySQL
sql时间段切分实现每隔x分钟出一份高速门架车流量
2022/02/28 SQL Server