Перетаскиваемые значки PyQt5 из списка в другое - PullRequest
0 голосов
/ 29 октября 2018

Я изо всех сил пытаюсь перетащить значки из списка (ViewMode установлен на IconMode) в другое. Это похоже на то, что я нашел в документах .

listviews example

Сценарий : пользователь перетаскивает QIcon 1 из ListView 1 и помещает его в ListView 2. ListView 2 должен добавить QIcon 1 в свою модель. Более того, я хочу сделать некоторую фоновую работу, когда определенный QIcon добавлен в ListView 2. Как я узнаю, что QIcon 1 был перенесен в ListView 2, а не QIcon 2?

mainwindow (устанавливает макет, загружает изображения в просмотр списка 1):

class Ui_MainWindow(object):
...
    def loadImages(self):
        model = QStandardItemModel()
        images = Path("images").glob("*.*")
        for image in images:
            item = QStandardItem()
            item.setIcon(QIcon(str(image)))
            model.appendRow(item)

        self.listView1.setModel(model)

просмотр списка 1:

class ListView1(QListView):
    def __init__(self):
        super().__init__()
        self.setAcceptDrops(False)
        self.setViewMode(QtWidgets.QListView.IconMode)
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.setIconSize(QSize(50, 50))
        self.setResizeMode(QtWidgets.QListView.Adjust)
        self.setDragDropMode(QAbstractItemView.DragOnly)

listview 2:

class ListView2(QListView):
    def __init__(self):
        super().__init__()
        self.setViewMode(QtWidgets.QListView.IconMode)
        self.setDragDropMode(QAbstractItemView.DropOnly)
        self.setIconSize(QSize(50, 50))
        self.setAcceptDrops(True)

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

    def dragMoveEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        event.accept()
        event.setDropAction(QtCore.Qt.MoveAction)
        event.acceptProposedAction()

Как перетащить значок из списка 1 в список 2 и получить доступ к его свойствам?

1 Ответ

0 голосов
/ 30 октября 2018

Нет необходимости перезаписывать dragEnterEvent, dragMoveEvent или dropEvent, поскольку эти реализации уже существуют и работают правильно, пример, на который вы указываете, для других типов виджетов, в которых эти события не реализованы.

from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets

class LListView(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(LListView, self).__init__(parent)
        self.model = QtGui.QStandardItemModel(self)
        self.setModel(self.model)

        self.setAcceptDrops(False)
        self.setViewMode(QtWidgets.QListView.IconMode)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setIconSize(QtCore.QSize(50, 50))
        self.setResizeMode(QtWidgets.QListView.Adjust)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)

class RListView(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(RListView, self).__init__(parent)
        self.model = QtGui.QStandardItemModel(self)
        self.setModel(self.model)

        self.setAcceptDrops(True)
        self.setViewMode(QtWidgets.QListView.IconMode)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setIconSize(QtCore.QSize(50, 50))
        self.setResizeMode(QtWidgets.QListView.Adjust)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        central_widget = QtWidgets.QWidget()
        self.l_view = LListView()
        self.r_view = RListView()

        self.setCentralWidget(central_widget)
        lay = QtWidgets.QHBoxLayout(central_widget)
        lay.addWidget(self.l_view)
        lay.addWidget(self.r_view)
        self.loadImages()

    def loadImages(self):
        images = Path("images").glob("*.*")
        for image in images:
            item = QtGui.QStandardItem()
            item.setIcon(QtGui.QIcon(str(image)))
            self.l_view.model.appendRow(item)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

Обновление:

Если вы хотите добавить идентификатор, это можно сделать с помощью роли, которую вы передаете при создании элемента, а затем в dropEvent() получите все роли, затем получите нужную вам роль и через нее идентификатор:

from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets

class LListView(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(LListView, self).__init__(parent)
        self.m_model = QtGui.QStandardItemModel(self)
        self.setModel(self.m_model)

        self.setAcceptDrops(False)
        self.setViewMode(QtWidgets.QListView.IconMode)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setIconSize(QtCore.QSize(50, 50))
        self.setResizeMode(QtWidgets.QListView.Adjust)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)

class RListView(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(RListView, self).__init__(parent)
        self.m_model = QtGui.QStandardItemModel(self)
        self.setModel(self.m_model)

        self.setAcceptDrops(True)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.setIconSize(QtCore.QSize(50, 50))
        self.setResizeMode(QtWidgets.QListView.Adjust)
        self.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)

    def dropEvent(self, event):
        last_row_count = self.model().rowCount()
        super(RListView, self).dropEvent(event)
        # check if an item is added
        if self.model().rowCount() > last_row_count:
            md = event.mimeData()
            fmt = "application/x-qabstractitemmodeldatalist"
            if md.hasFormat(fmt):
                encoded = md.data(fmt)
                stream = QtCore.QDataStream(encoded, QtCore.QIODevice.ReadOnly)
                datas = []
                item = {}
                while not stream.atEnd():
                    row = stream.readInt32()
                    column = stream.readInt32()
                    map_items = stream.readInt32()
                    for i in range(map_items):
                        key = stream.readInt32()
                        value = QtCore.QVariant()
                        stream >> value
                        item[QtCore.Qt.ItemDataRole(key)] = value
                    datas.append(item)
                for data in datas:
                    identifier = data[QtCore.Qt.UserRole+1].value()
                    print("identifier: ", identifier)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        central_widget = QtWidgets.QWidget()
        self.l_view = LListView()
        self.r_view = RListView()

        self.setCentralWidget(central_widget)
        lay = QtWidgets.QHBoxLayout(central_widget)
        lay.addWidget(self.l_view)
        lay.addWidget(self.r_view)
        self.loadImages()

    def loadImages(self):
        images = Path("images").glob("*.*")
        for i, image in enumerate(images):
            item = QtGui.QStandardItem()
            identifier = "img_{:06d}".format(i+1)
            item.setData(identifier, QtCore.Qt.UserRole+1)
            item.setIcon(QtGui.QIcon(str(image)))
            self.l_view.m_model.appendRow(item)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
...