如何能够在 QListWidgets 之间拖放项目并且仍然能够使用拖放进行排序

How to be able to drag and drop items between QListWidgets and still be able to sort using drag and drop

我继承了两个 QListView 类,一个 SourceListWidgetAcceptListWidget 我希望能够将项目从 SourceListWidget 复制到 AcceptListWidget 并且仍然能够使用拖放在 AcceptListWidget 中对它们进行排序。

在下面的代码中,除了 AcceptListWidget 无法使用拖放进行排序外,一切都按照我想要的方式进行。另外我想知道是否有办法从 SourceListWidget 中插入一个项目到 AcceptListWidget 而不是仅仅将它附加到末尾。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, \
    QVBoxLayout, QListWidget, QAbstractItemView
from PyQt5.QtGui import QDragMoveEvent, QDropEvent
from PyQt5.QtCore import Qt, QMimeData
import typing


class AcceptListWidget(QListWidget):
    def __init__(self):
        super().__init__()
        self.setDefaultDropAction(Qt.MoveAction)
        self.setDragDropMode(QAbstractItemView.InternalMove)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, e: QDragMoveEvent) -> None:
        e.accept()

    def dragMoveEvent(self, e: QDragMoveEvent) -> None:
        e.accept()

    def mimeTypes(self) -> typing.List[str]:
        return ['text/json']

    def mimeData(self, indexes) -> QMimeData:
        drag_data = indexes[0].text()
        mime_data = QMimeData()
        mime_data.setText(drag_data)
        return mime_data

    def dropEvent(self, event: QDropEvent) -> None:
        event.setDropAction(Qt.CopyAction) if event.source() != self else event.setDropAction(Qt.MoveAction)
        if event.source() != self:
            self.addItem(event.mimeData().text())



class SourceListWidget(QListWidget):
    def __init__(self):
        super().__init__()
        self.setDragDropMode(QAbstractItemView.DragDrop)

    def dragMoveEvent(self, e: QDragMoveEvent) -> None:
        e.accept() if e.source() != self else e.ignore()

    def mimeTypes(self) -> typing.List[str]:
        return ['text/json']

    def mimeData(self, indexes) -> QMimeData:
        drag_data = indexes[0].text()
        mime_data = QMimeData()
        mime_data.setText(drag_data)
        return mime_data

    def dropMimeData(self, index: int, data: QMimeData, action: Qt.DropAction) -> bool:
        print('dropMimeData')
        drop_data = data.data('text')
        for item in drop_data:
            if item in self.stringList():
                self.removeRow(self.stringList().index(item))
        return True

    def dragEnterEvent(self, e):
        e.accept()

    def dropEvent(self, event: QDropEvent) -> None:
        event.setDropAction(Qt.MoveAction)
        event.accept()


class Widget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.widget_layout = QVBoxLayout()
        self.accept_widget = AcceptListWidget()
        self.accept_widget.setFlow(QListWidget.LeftToRight)
        # Create ListWidget and add 10 items to move around.
        self.list_widget = SourceListWidget()
        self.list_widget.setFlow(QListWidget.LeftToRight)
        for x in range(1, 11):
            self.list_widget.addItem('Item {:02d}'.format(x))

        for x in range(1, 2):
            self.accept_widget.addItem('Item {:02d}'.format(x))
        self.widget_layout.addWidget(self.accept_widget)
        self.widget_layout.addWidget(self.list_widget)
        self.setLayout(self.widget_layout)


if __name__ == '__main__':
  app = QApplication(sys.argv)
  widget = Widget()
  widget.show()

  sys.exit(app.exec_())

我要修复的主要方面是 AcceptListWidget 的内部排序,但是如果可以将项目放入从 SourceListWidgetAcceptListWidget 的某些位置,那将是更好。

默认情况下,QListWidget 接受项目的重新排序,因此您只需在源为外部时调用父级的方法:

def dropEvent(self, event: QDropEvent) -> None:
    if event.source() is self:
        super().dropEvent(event)
    else:
        event.setDropAction(Qt.CopyAction)
        self.addItem(event.mimeData().text())