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

时间:2019-04-17 02:51:36

标签: python python-3.x pyqt pyqt5 qlistwidget

I have two QListView inherited classes, a SourceListWidget and AcceptListWidget I want to be able to copy items from SourceListWidget to AcceptListWidget and still be able to sort them in the AcceptListWidget using dragging and dropping.

In the code below everything works the way I want it to other than the AcceptListWidget is unable to be sorted using drag and drop. Also I'm wondering if there's a way to insert an item into the AcceptListWidget from the SourceListWidgetinstead of just appending it to the end.

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_())

The major aspect that I'm trying to fix is the internal sorting of the AcceptListWidget but if items can be dropped into certain places from SourceListWidget to AcceptListWidget that would be even better.

1 个答案:

答案 0 :(得分:1)

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

forEach
相关问题