PyQt элемент просмотра пользовательского перетаскивания - PullRequest
2 голосов
/ 18 апреля 2019

Я работаю над пользовательской реализацией перетаскивания в QTableView.Когда я перетаскиваю ячейку и помещаю ее в другую ячейку, я хочу вручную изменить некоторые данные в модели на основе того, что было перетащено и куда было отброшено.Как я могу это сделать?Я перечитывал всю документацию по Qt, но я совершенно потерян, и, в частности, с помощью drag-drop кажется, что преобразование C ++ в PyQt немного менее интуитивно понятно.Я хочу знать, какие клетки были изначально перетащены, и куда они были сброшены.Где моя путаница, кажется, с QMimeData.Из того, что я могу сказать, когда начинается перетаскивание, событие перетаскивания получает правильные данные MIME, но я не знаю, как получить это в PyQt (я мог делать подобные вещи с текстом и URL-адресами в прошлом, но я 'м потеряно, когда дело доходит до просмотра товара).Мне также нужно знать, куда я захожу.Я думаю, я мог бы сделать «элемент на позиции курсора», но я предполагаю, что эти данные уже существуют в событии перетаскивания, и мне просто нужно выяснить, как запросить его.

Вот простой пример:

import sys
from PyQt4 import QtGui, QtCore


class TableView(QtGui.QTableView):
     def __init__(self, parent=None):
         QtGui.QTreeWidget.__init__(self, parent)
         self.setDragEnabled(True)
         self.setDropIndicatorShow(True)
         self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
         self.setDragDropOverwriteMode(False)
         self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

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

    def dropEvent(self, event):
        # I want to do cool things with the dragged cells, and I need to know where they dropped!
        print(event.mimeData().formats()) # this tells me that I shuld get some sort of "qabstractitemmodeldatalist". Sounds promising...
        print(event.mimeData().data("application/x-qabstractitemmodeldatalist")) # this gives me an interesting looking QByteArray but I have no idea what to do with it...
        event.accept()

class Dialog(QtGui.QDialog):
    def __init__(self):
        super(Dialog, self).__init__()

        model = QtGui.QStandardItemModel(self)
        model.insertRow(0, QtGui.QStandardItem("C"))
        model.insertRow(0, QtGui.QStandardItem("B"))
        model.insertRow(0, QtGui.QStandardItem("A"))

        table = TableView(self)
        table.setModel(model)

app = QtGui.QApplication(sys.argv)
ex = Dialog()
ex.show()
sys.exit(app.exec_())

1 Ответ

1 голос
/ 18 апреля 2019

Вы не можете знать, куда они были перетащены, поскольку mimeData не имеет этой информации, но вы можете перетащить данные, для этого мы создали временную модель, в которой мы установим mimeData, имитирующую то же поведение перетаскивания. Чтобы получить, где он был отброшен, позиция, которая является частью события, должна использоваться вместе с indexAt (), получая, таким образом, QModelIndex:

import sys
from PyQt4 import QtGui, QtCore


class TableView(QtGui.QTableView):
    def __init__(self, parent=None):
        QtGui.QTreeWidget.__init__(self, parent)
        self.setDragEnabled(True)
        self.setDropIndicatorShown(True)
        self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
        self.setDragDropOverwriteMode(False)
        self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

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

    def dropEvent(self, event):
        if self.viewport().rect().contains(event.pos()):
            fake_model = QtGui.QStandardItemModel()
            fake_model.dropMimeData(
                event.mimeData(), event.dropAction(), 0, 0, QtCore.QModelIndex()
            )
            print("from:")
            for r in range(fake_model.rowCount()):
                for c in range(fake_model.columnCount()):
                    ix = fake_model.index(r, c)
                    print(ix.data())
            to_index = self.indexAt(event.pos())
            if to_index.isValid():
                print("to:", to_index.data())
        super(TableView, self).dropEvent(event)


class Dialog(QtGui.QDialog):
    def __init__(self):
        super(Dialog, self).__init__()

        model = QtGui.QStandardItemModel(self)
        for letter in "ABC":
            model.appendRow(QtGui.QStandardItem(letter))

        table = TableView()
        table.setModel(model)

        lay = QtGui.QVBoxLayout(self)
        lay.addWidget(table)


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    ex = Dialog()
    ex.show()
    sys.exit(app.exec_())
...