pyqt 5カスタムドラッグ&ドロップ機能の実装説明
サンプルは依然として『Rapid GUI Programming with Python and Qt』から来ている.中国語版240ページはドラッグアンドドロップのサポートについて重要な説明がありますが、少し言葉がはっきりしないので、コード部分と結びつけてもう一度自分に説明します.本には次のように書かれています.
setAcceptDrops()メソッドはQWidgetから継承されていますが、setDragEnabled()はそうではありませんので、デフォルトでは一部のウィンドウコンポーネントでのみ使用できます.ドロップ操作をサポートできるカスタムウィンドウコンポーネントを作成する場合は、前述の例のようにsetAcceptDrops(True)を簡単に呼び出し、dragEnterEvent()、dragMoveEvent、dropEvent()を再実装するだけでよい.このカスタムウィンドウがドラッグをサポートし、ウィンドウがQWidgetから継承されているか、setDragEnabled()のないQWidgetサブクラスから継承されている場合は、コンポーネントにdragをサポートする2つのことをする必要があります.一つは、Qdragオブジェクトを作成できるようにstartDrag()メソッドを提供することであり、もう一つは、startDrag()メソッドを適切な時間に呼び出すことができることを確保することである.startDrag()の呼び出しを確保する最も簡単な方法はmouseMoveEventの再実現......コードを振り返って、上記の説をどのように実行するかです.
2つ目の例は、祖先に徳があり、dragを支持している.
3つ目の例は自己奮闘型の鳳凰男です
setAcceptDrops()メソッドはQWidgetから継承されていますが、setDragEnabled()はそうではありませんので、デフォルトでは一部のウィンドウコンポーネントでのみ使用できます.ドロップ操作をサポートできるカスタムウィンドウコンポーネントを作成する場合は、前述の例のようにsetAcceptDrops(True)を簡単に呼び出し、dragEnterEvent()、dragMoveEvent、dropEvent()を再実装するだけでよい.このカスタムウィンドウがドラッグをサポートし、ウィンドウがQWidgetから継承されているか、setDragEnabled()のないQWidgetサブクラスから継承されている場合は、コンポーネントにdragをサポートする2つのことをする必要があります.一つは、Qdragオブジェクトを作成できるようにstartDrag()メソッドを提供することであり、もう一つは、startDrag()メソッドを適切な時間に呼び出すことができることを確保することである.startDrag()の呼び出しを確保する最も簡単な方法はmouseMoveEventの再実現......コードを振り返って、上記の説をどのように実行するかです.
class DropLineEdit(QLineEdit):
"""QLineEdit QWidget, step ' '"""
def __init__(self, parent=None):
super(DropLineEdit, self).__init__(parent)
self.setAcceptDrops(True) #step1 True
self.setToolTip("DropLineEdit")
def dragEnterEvent(self, event): #step2 dragEnterEvent:accept
if event.mimeData().hasFormat("application/x-icon-and-text"):
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event): #step3 dragMoveEvent:Copy or Move
if event.mimeData().hasFormat("application/x-icon-and-text"):
event.setDropAction(Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event): #step4 dropEvent:get data
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.readQString()
self.setText(text)
event.setDropAction(Qt.CopyAction)
event.accept()
else:
event.ignore()
2つ目の例は、祖先に徳があり、dragを支持している.
class DnDListWidget(QListWidget):
"""QListWidget , QAbstractItemView, setDragEnabled(),
True, startDrag() Drag """
def __init__(self, parent=None):
super(DnDListWidget, self).__init__(parent)
self.setAcceptDrops(True)
self.setDragEnabled(True)
self.setToolTip("DnDListWidget")
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 = stream.readQString()
# text=""
# stream>>text
icon = QIcon()
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.writeQString(item.text())
# stream<
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))
3つ目の例は自己奮闘型の鳳凰男です
class DnDWidget(QWidget):
""" Qwidget, Drag, startDrag() , mouseMoveEvent"""
def __init__(self, text, icon=QIcon(), parent=None):
super(DnDWidget, self).__init__(parent)
self.setAcceptDrops(True) #drop step1
#self.setDragEnabled(True), , 'DnDWidget' object has no attribute 'setDragEnabled'
self.text = text
self.icon = icon
self.setToolTip("DnDWidget")
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): #drops step2
if event.mimeData().hasFormat("application/x-icon-and-text"):
event.accept()
else:
event.ignore()
def dragMoveEvent(self, event):#drop step3
if event.mimeData().hasFormat("application/x-icon-and-text"):
event.setDropAction(Qt.CopyAction)
event.accept()
else:
event.ignore()
def dropEvent(self, event): #drop step4 over
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.text = stream.readQString()
self.icon = QIcon()
stream >> self.icon
event.setDropAction(Qt.CopyAction)
event.accept()
self.updateGeometry()
self.update()
else:
event.ignore()
def mouseMoveEvent(self, event):
self.startDrag() #drag step 1
QWidget.mouseMoveEvent(self, event)
def startDrag(self): #drag step 2
icon = self.icon
if icon.isNull():
return
data = QByteArray()
stream = QDataStream(data, QIODevice.WriteOnly)
stream.writeQString(self.text)
# stream<
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)