Drag and Drop in PyQt
January 14, 2011 @ 10:54
So you want to be able to drag items out of a QListView? The docs suck on this. Here’s how simple it actually is:
class MyListView(QtGui.QListView):
def __init__(self, parent=None):
super(MyListView, self).__init__(parent)
# enable dragging
self.setDragEnabled(True)
# I'm only interested in drag, not drop, so I disable drop
self.setAcceptDrops(False)
self.setDragDropMode(QtGui.QAbstractionItemView.DragOnly)
# use this to allow selecting multiple entries
self.setSelectionMode(QtGui.QAbstractionItemView.ExtendedSelection)
def mouseMoveEvent(self, event):
self.dragObject()
def dragObject(self):
if not self.selectedIndexes():
return
drag = QtGui.QDrag(self)
data = []
for index in self.selectedIndexes():
if not index.isValid(): continue
# this assumes your model has a nodeFromIndex() method -
# it's easy to set one up, you'll probably have a custom
# model class anyways
node = self.model().nodeFromIndex(index)
data.append(str(node))
# in this case I'm just making a newline-seperated list
# of the data, you could do pretty much anything here
md = Qt.QMimeData()
md.setData('text/plain', "\n".join(data))
# this is important. Without this, it won't do anything.
# you can use different actions like Qt.MoveAction, which
# would remove the item from your model, but then your model
# has to be more complicated. I'm only interested in copy here.
drag.setMimeData(md)
dropAction = drag.exec_(Qt.Qt.CopyAction)
Yup, that’s it. There’s lots of conflicting docs, some tell you to do
complicated things with mousePressEvent()
, others are older than modern Qt,
others just plain wrong.