[PyQt] Drag-and-drop editing in QListWidget or QListView

Nathan Weston nathan at genarts.com
Wed Jun 22 18:27:36 BST 2011


On 6/7/2011 7:53 AM, Nathan Weston wrote:
>
>
> On 06/02/2011 07:42 PM, David Boddie wrote:
>> The draganddrop/puzzle example provided with PyQt uses a QListWidget to
>> display a collection of puzzle pieces that can be dropped inside or
>> outside
>> the list, though it's not exactly the most user friendly interface you
>> could imagine.
>>
>> The itemviews/puzzle example is more or less the same, but uses QListView
>> instead of QListWidget. It implements support for drag and drop in a
>> custom model, which is based on QAbstractListModel to make it as
>> simple as
>> possible. Strangely, the piece movement is quite a bit more intuitive
>> than
>> in the other example.
>>
>
> Thanks, that got me started in the right direction. It seems that I
> basically have to reimplement the InternalMove behavior myself -- it has
> some nice visual touches that aren't duplicated in the examples.
>
> This leaves me wondering, though -- if InternalMove doesn't give you any
> way to find out when things move, what's the point?
>

Update: after going around in circles with this for quite some time, I 
came to the conclusion that I really want to stick with the default drag 
and drop implementation using InternalMove. As soon as I override any 
part of that, I have to reimplement a ton of stuff (the pixmap for the 
QDrag(), the target indicators in the ListWidget, etc).

In case anyone is interested, this is the solution I came up with. It 
overrides startDrag and dropEvent in QListWidget in order to get the 
dragged item along with its old/new indices, but calls the superclass 
methods to do all the actual work.

It seems a little hacked-up to me, but it works.

It might be slightly cleaner to decode the the mime data in dropEvent -- 
I think this can hypothetically be decoded back into a QListWidgetItem. 
But I couldn't quite figure out how to do it.


class DragAndDropList(QListWidget):
     itemMoved = pyqtSignal(int, int, QListWidgetItem) # Old index, new 
index, item

     def __init__(self, parent=None, **args):
         super(DragAndDropList, self).__init__(parent, **args)

         self.setAcceptDrops(True)
         self.setDragEnabled(True)
         self.setDragDropMode(QAbstractItemView.InternalMove)
         self.drag_item = None
         self.drag_row = None

     def dropEvent(self, event):
         super(DragAndDropList, self).dropEvent(event)
         self.itemMoved.emit(self.drag_row, self.row(self.drag_item), 
self.drag_item)
         self.drag_item = None

     def startDrag(self, supportedActions):
         self.drag_item = self.currentItem()
         self.drag_row = self.row(self.drag_item)
         super(DragAndDropList, self).startDrag(supportedActions)


-- 
. . . . . . . . . . . . . . . . . . . . . . . . .
Nathan Weston                   nathan at genarts.com
GenArts, Inc.                   Tel: 617-492-2888
955 Mass. Ave                   Fax: 617-492-2852
Cambridge, MA 02139 USA         www.genarts.com


More information about the PyQt mailing list