Pyside 从一个 ListView 拖放到另一个

Posted

技术标签:

【中文标题】Pyside 从一个 ListView 拖放到另一个【英文标题】:Pyside Drag and Drop from one ListView to another 【发布时间】:2020-03-29 09:23:57 【问题描述】:

我正在尝试深入研究 QlistView 和模型,因此明确使用了 QListWidgets 以上的内容。但是我确实有问题使从一个拖放到另一个成为可能。更准确地说,到目前为止,我还没有捕捉到任何事件。

我必须简单的列表。其中之一按预期显示项目。但是一旦我将项目拖到另一个列表中,应用程序就会关闭。 目前我只有简单的数据,但是一旦我弄清楚了接口,这些数据可能会变得更加复杂。

一个简化和精简的版本:

from PySide2 import QtWidgets, QtCore
from PySide2.QtCore import QStringListModel


class ListView(QtWidgets.QListView):

    def __init__(self, items=[], parent=None):
        super(ListView, self).__init__(parent)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
        self.setDropIndicatorShown(True)
        self.setMaximumWidth(250)
        model = ListModel(items)
        self.setModel(model)

    def dragEnterEvent(self, event):
        super(ListView, self).dragEnterEvent(event)
        print event

    def dragLeaveEvent(self, event):
        super(ListView, self).dragLeaveEvent(event)
        print event

    def dragMoveEvent(self, event):
        super(ListView, self).dragMoveEvent(event)
        print event

    def dropEvent(self, event):
        super(ListView, self).dropEvent(event)
        print event


class ListModel(QStringListModel):
    def __init__(self, items, *args, **kwargs):
        super(ListModel, self).__init__(*args, **kwargs)
        self.items = items or []

    def data(self, index, role):
        if role == QtCore.Qt.DisplayRole:
            return self.items[index.row()]

    def rowCount(self, index):
        return len(self.items)


class View(QtWidgets.QWidget):

    def __init__(self):
        super(View, self).__init__()
        self.list_one = ListView(["Peter", "Bjoern", "John"], parent=self)
        self.list_two = ListView(parent=self)
        main_layout = QtWidgets.QHBoxLayout()
        main_layout.addWidget(self.list_one)
        main_layout.addWidget(self.list_two)
        self.setLayout(main_layout)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    view = View()
    view.show()
    app.exec_()

【问题讨论】:

【参考方案1】:

至少你需要设置 QMimeData 文本以便它被传递,然后在dropEvent 设置新的列表模型。

def dragEnterEvent(self, event):
    if not event.mimeData().hasText():
        event.mimeData().setText(self.currentIndex().data())
    event.accept()

def dragMoveEvent(self, event):
    if event.mimeData().hasText():
        event.accept()
    else:
        event.ignore()

def dropEvent(self, event):
    if event.mimeData().hasText():
        items = self.model().items + [event.mimeData().text()]
        self.setModel(ListModel(items))
        event.accept()
    else:
        event.ignore()

结果:

【讨论】:

每次丢弃物品时都必须创建模型似乎效率低下。我不认为这是正确的。 当然没必要,我只是展示了如何让拖放工作。 有人还有完整的代码吗?我试过这个,它在 PySide2 和 PySide6 上都有段错误

以上是关于Pyside 从一个 ListView 拖放到另一个的主要内容,如果未能解决你的问题,请参考以下文章

将 Windows 桌面快捷方式拖放到 listView

拖放到桌面/资源管理器

PyQt5 可拖动图标从列表视图到另一个

如何将下拉列表视图项目拖放到另一个列表视图

React Native ListView 项目 ZIndex

PySide2 拖放功能不起作用