SoFunction
Updated on 2024-11-15

python3+PyQt5 reimplementation of custom data drag-and-drop processing

This article is divided into two parts, the first part through the python3 + PyQt5 to realize the drag and drop operation of custom data. The second part of the first part of the program is modified to increase the drag and drop operation, the menu prompts whether to move or copy, there can be ctrl keyboard to set the move process to copy the source instead of deleting the source.

The custom data MIME data type QMimeData, MIME is a standardized format for handling custom data with multiple components.MIME data consists of a data type and a subtype-for example, text/plain, text/html, image/png.To handle custom MIME data consists of a data type and a subtype-for example, text/plain, text/html, image/png. To work with custom MIME data, you must choose a custom data type and a subtype, and then encapsulate the data in a QMimeData object. In this example, we create new MIME data of type application/x-icon-and-text.

Notes:

dragEnterEvent This is a drag and drop event function, we drag and drop the file into the program interface to open, before you must setAcceptDrops(true) after dragging and dropping, but only set acceptDrops is not enough, you also need to dragEnterEvent event in the dragged object to screen, determine the mimeData is of a type you can handle, and if so, call () to release it. The dropEvent event is generated at the end of the drag and drop, where the final placement operation is performed. In short this is a drag and drop event function that filters events and places them.

Part I:

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

class DropLineEdit(QLineEdit):

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


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   ()
   ()
  else:
   ()


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


class DnDListWidget(QListWidget):

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


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   ()
   ()
  else:
   ()


 def dropEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   data = ().data("application/x-icon-and-text")
   stream = QDataStream(data, )
   text = ""
   icon = QIcon()
   #stream >> text >> icon
   text=()
   stream >> icon
   item = QListWidgetItem(text, self)
   (icon)
   ()
   ()
  else:
   ()


 def startDrag(self, dropActions):
  item = ()
  icon = ()
  data = QByteArray()
  stream = QDataStream(data, )
  #stream << () << icon
  (())
  stream << icon
  mimeData = QMimeData()
  ("application/x-icon-and-text", data)
  drag = QDrag(self)
  (mimeData)
  pixmap = (24, 24)
  (QPoint(12, 12))
  (pixmap)
  if () == :
   ((item))


class DnDWidget(QWidget):

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


 def minimumSizeHint(self):
  fm = QFontMetricsF(())
  if ():
   return QSize((), () * 1.5)
  return QSize(34 + (), max(34, () * 1.5))


 def paintEvent(self, event):
  height = QFontMetricsF(()).height()
  painter = QPainter(self)
  ()
  ()
  ((), QColor().lighter())
  if ():
   (10, height, )
  else:
   pixmap = (24, 24)
   (0, 5, pixmap)
   (34, height,
         + " (Drag to or from me!)")


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   ()
   ()
  else:
   ()


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

   ()
   ()
   ()
   ()
  else:
   ()


 def mouseMoveEvent(self, event):
  ()
  (self, event)


 def startDrag(self):
  icon = 
  if ():
   return
  data = QByteArray()
  stream = QDataStream(data, )
  #stream <<  << icon
  ()
  stream<<icon
  mimeData = QMimeData()
  ("application/x-icon-and-text", data)
  drag = QDrag(self)
  (mimeData)
  pixmap = (24, 24)
  (QPoint(12, 12))
  (pixmap)
  ()


class Form(QDialog):

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

  dndListWidget = DnDListWidget()
  path = (__file__)
  for image in sorted(((path, "images"))):
   if (".png"):
    item = QListWidgetItem((".")[0].capitalize())
    (QIcon((path,
         "images/{0}".format(image))))
    (item)
  dndIconListWidget = DnDListWidget()
  ()
  dndWidget = DnDWidget("Drag to me!")
  dropLineEdit = DropLineEdit()

  layout = QGridLayout()
  (dndListWidget, 0, 0)
  (dndIconListWidget, 0, 1)
  (dndWidget, 1, 0)
  (dropLineEdit, 1, 1)
  (layout)

  ("Custom Drag and Drop")

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

Run results:

Part II:

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

class DropLineEdit(QLineEdit):

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


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   ()
   ()
  else:
   ()


 def dropEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   data = ().data("application/x-icon-and-text")
   stream = QDataStream(data, )
   text = ""
   text=()
   (text)
   ()
   ()
  else:
   ()


class DnDMenuListWidget(QListWidget):

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


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   ()
   ()
  else:
   ()


 def dropEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   data = ().data("application/x-icon-and-text")
   stream = QDataStream(data, )
   text = ""
   icon = QIcon()
   text=()
   stream>>icon
   menu = QMenu(self)
   ("&Copy", )
   ("&Move", )
   if menu.exec_(()):
    item = QListWidgetItem(text, self)
    (icon)
    ()
    ()
    return
   else:
    ()
  ()


 def setCopyAction(self):
   = 


 def setMoveAction(self):
   = 


 def startDrag(self, dropActions):
  item = ()
  icon = ()
  data = QByteArray()
  stream = QDataStream(data, )
  (())
  stream<<icon
  mimeData = QMimeData()
  ("application/x-icon-and-text", data)
  drag = QDrag(self)
  (mimeData)
  pixmap = (24, 24)
  (QPoint(12, 12))
  (pixmap)
  if ((|) == ):
   ((item))


class DnDCtrlListWidget(QListWidget):

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


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   action = 
   if () & :
    action = 
   (action)
   ()
  else:
   ()


 def dropEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   data = ().data("application/x-icon-and-text")
   stream = QDataStream(data, )
   text = ""
   icon = QIcon()
   text=()
   stream>>icon
   item = QListWidgetItem(text, self)
   (icon)
   action = 
   if () & :
    action = 
   (action)
   ()
  else:
   ()


 def startDrag(self, dropActions):
  item = ()
  icon = ()
  data = QByteArray()
  stream = QDataStream(data, )
  (())
  stream<<icon
  mimeData = QMimeData()
  ("application/x-icon-and-text", data)
  drag = QDrag(self)
  (mimeData)
  pixmap = (24, 24)
  (QPoint(12, 12))
  (pixmap)
  if ((|) == ):
   ((item))


class DnDWidget(QWidget):

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


 def minimumSizeHint(self):
  fm = QFontMetricsF(())
  if ():
   return QSize((), () * 1.5)
  return QSize(34 + (), max(34, () * 1.5))


 def paintEvent(self, event):
  height = QFontMetricsF(()).height()
  painter = QPainter(self)
  ()
  ()
  ((), QColor().lighter())
  if ():
   (10, height, )
  else:
   pixmap = (24, 24)
   (0, 5, pixmap)
   (34, height,
         + " (Drag to or from me!)")


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


 def dragMoveEvent(self, event):
  if ().hasFormat("application/x-icon-and-text"):
   ()
   ()
  else:
   ()


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

   ()
   ()
   ()
   ()
  else:
   ()


 def mouseMoveEvent(self, event):
  ()
  (self, event)


 def startDrag(self):
  icon = 
  if ():
   return
  data = QByteArray()
  stream = QDataStream(data, )
  ()
  stream<<icon
  mimeData = QMimeData()
  ("application/x-icon-and-text", data)
  drag = QDrag(self)
  (mimeData)
  pixmap = (24, 24)
  (QPoint(12, 12))
  (pixmap)
  ()


class Form(QDialog):

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

  dndListWidget = DnDMenuListWidget()
  path = (__file__)
  for image in sorted(((path, "images"))):
   if (".png"):
    item = QListWidgetItem((".")[0].capitalize())
    (QIcon((path,
         "images/{0}".format(image))))
    (item)
  dndIconListWidget = DnDCtrlListWidget()
  ()
  dndWidget = DnDWidget("Drag to me!")
  dropLineEdit = DropLineEdit()

  layout = QGridLayout()
  (dndListWidget, 0, 0)
  (dndIconListWidget, 0, 1)
  (dndWidget, 1, 0)
  (dropLineEdit, 1, 1)
  (layout)

  ("Custom Drag and Drop")

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

Run results:

This is the whole content of this article.