Pergunta

I'm having trouble implementing a QListWidget with custom items that can be reordered by dragging and dropping. The problem is when I make a fast double click (a very short drag&drop) on an item, the item sometimes disappears from the QListWidget.

This is the constructor for my Widget:

ListPopisiDragDrop::ListPopisiDragDrop(QWidget *parent) :
    QListWidget(parent)
{
    setSelectionMode(QAbstractItemView::SingleSelection);
    setDragEnabled(true);
    viewport()->setAcceptDrops(true);
    setDefaultDropAction(Qt::MoveAction);
    setDropIndicatorShown(true);
    setDragDropMode(QAbstractItemView::InternalMove);
}

also the drop event:

void ListPopisiDragDrop::dropEvent(QDropEvent *event){

    int startRow=currentIndex().row();

    QListWidget::dropEvent(event);

    int endRow=currentIndex().row();

    //more code...
}

Custom items are made by implementing paint() and sizeHint() functions from QAbstractItemDelegate.

When the problem with disappearing items happens, the dropEvent isn't even called.

I really don't know what is happening and if I'm doing something wrong. Any help is appreciated.

Thanks!

Edit: I'm running the application on a Symbian S60 5th edition phone.

Edit2: If I add this line to the constructor:

setDragDropOverwriteMode(true);

the item in the list still disappears, but an empty row stays in it's place.

Edit3: I've added this code to see what is happening:

bool ListPopisiDragDrop::event(QEvent *e){
    qDebug()<<"new event, type: "<<e->type()<<", listCount: "<<this->count();

    QListWidget::event(e);
}

I've also printed "drop event" when the drop event is called. This gives me the following output:

...
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  68 , listCount:  2 
[Qt Message] DROPEVENT 
[Qt Message] new event, type:  71 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  68 , listCount:  2 
[Qt Message] DROPEVENT 
[Qt Message] new event, type:  71 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  2 
[Qt Message] new event, type:  68 , listCount:  2 
[Qt Message] new event, type:  12 , listCount:  1 
[Qt Message] new event, type:  12 , listCount:  1 
[Qt Message] new event, type:  1 , listCount:  1
...

As you can see, after event type 68, the listCount changes from 2 to 1 (one item disappears). I'm still not getting where the problem is...

Edit4: I'm having the same behavior even when I'm not using custom items. Still can't figure out what's wrong.

Edit5: Even the example from [1] has the same behavior when tested on the mobile device. Could the Qt version be a problem? I'm using Qt for Symbian Devices version 4.6.3...

[1]http://www.java2s.com/Code/Cpp/Qt/QListWidgetdraganddrop.htm

Foi útil?

Solução

I can think of 2 reasons for this behaviour: the signal itemDoubleClicked is handled somewhere in your QListWidget and does something unintendet, or your "more code" in dropEvent does something bad when source and destination are the same (you could check if startRow is equal to endRow and do nothing in this case).

Edit:

Does this program work for you:

#include <QApplication>
#include <QListWidget>

int main(int argc, char **argv)
{
    QApplication a(argc, argv);

    QListWidget lw;

    for(int i = 1; i < 10; ++i)
        lw.addItem(new QListWidgetItem(QString("Item %1").arg(i)));
    lw.setDragEnabled(true); // ***
    lw.viewport()->setAcceptDrops(true); // ***
    lw.setDefaultDropAction(Qt::MoveAction); // ***
    lw.setDropIndicatorShown(true); // ***

    lw.setDragDropMode(QAbstractItemView::InternalMove);

    lw.show();

    a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
    a.exec();
}

Lines with three stars can be deleted. This program works for me on Windows XP with Qt 4.7.1, compiled with VS2010.

Outras dicas

Had same problem on desktop once, with SelectionMode, InternalMove etc. exactly as shown. Also had my own model for the view, so I just made it return that way:

Qt::ItemFlags MyModel::flags(const QModelIndex& index) const
{
    if (index.isValid())
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
}

Worked fine with me.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top