Qt:使用拖放重新排序 ListView 项目

标签 qt drag-and-drop qlistview

我实现了以下拖放方法

void mousePressEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
void startDrag(Qt::DropActions supportedActions);

我有一个 QListView 并使用 setIndexWidget() 在每个模型索引处显示自定义小部件。我试图使用拖放来排列 ListView 中的项目,但是 ListView 中的项目排列不正确,我编写了以下代码:-

MyListView::MyListView(QWidget *parent) :
    QListView(parent)
{
    setSelectionMode(QAbstractItemView::SingleSelection);
    setDragEnabled(true);
    setAcceptDrops(true);
    setDragDropMode(QAbstractItemView::InternalMove);
    setDefaultDropAction(Qt::MoveAction);
    setDropIndicatorShown(true);
    setDragDropOverwriteMode(true);
    setMovement(QListView::Snap);
    setFlow(QListView::TopToBottom);
//    setStyleSheet("QListView::item {"
//                  "height: 50px;"
//                  "border: 1px solid black;}");
}

void MyListView::setModel(QAbstractItemModel *model)
{
    QListView::setModel(model);

    for (int i=0; i<model->rowCount(); i++)
    {
        QModelIndex index = model->index(i,0);
        ListWidgetItem *widget = new ListWidgetItem;
        widget->setIndex(i);;
        setIndexWidget(index,widget);
    }
}

void MyListView::mousePressEvent(QMouseEvent *event)
{
    QModelIndex i = indexAt(event->pos());
    if (event->button() ==  Qt::LeftButton)
    {
        ListWidgetItem *item = dynamic_cast<ListWidgetItem *>(childAt(event->pos()));

        if (!item)
            return;

        y = event->pos().y()-item->pos().y();

        QModelIndex indx = indexAt(event->pos());
        currentPixmap = QPixmap::grabWidget(item);
        dragPoint = event->pos();
        if (event->pos().x() < 25 && indx.row() >= 0)
            startDrag(Qt::MoveAction);
    }
}

void MyListView::dragEnterEvent(QDragEnterEvent *event)
{
   if (event->mimeData()->hasFormat("application/x-QListView-DragAndDrop"))
   {
       event->accept();
   }
    else
        event->ignore();
}

void MyListView::dragMoveEvent(QDragMoveEvent *event)
{
    ListWidgetItem *item = dynamic_cast<ListWidgetItem *>(childAt(event->pos()));
    if(!item)
        return;

    itemList.append(item);

    foreach (ListWidgetItem *widget,itemList)
    {
        if (widget == item)
            widget->setStyleSheet("#ListWidget { border-top: 2px solid red; }");
        else
            widget->setStyleSheet("#ListWidget { border-top: 0px solid black; }");
    }
    if (event->mimeData()->hasFormat("application/x-QListView-DragAndDrop"))
    {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    } else
        event->ignore();
}

void MyListView::dropEvent(QDropEvent *event)
{
    if (event->mimeData()->hasFormat("application/x-QListView-DragAndDrop")) {
        QByteArray itemData = event->mimeData()->data("application/x-QListView-DragAndDrop");
        QDataStream dataStream(&itemData,QIODevice::ReadOnly);

        QPoint itemPoint;
        dataStream >> itemPoint;

        ListWidgetItem *item = dynamic_cast<ListWidgetItem *> (childAt(itemPoint));
        if(!item)
            return;

        QModelIndex index = indexAt(event->pos());
        int row = index.row();
        model()->insertRows(row,1);

        QModelIndex idx =model()->index(row,0);
        setIndexWidget(idx,item);

        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            foreach (ListWidgetItem *widget,itemList)
            {
                widget->setStyleSheet("#ListWidget { border-top: 0px solid black; }");
            }
            itemList.clear();
//            model()->removeRow(n+1);

            event->accept();
        }
    } else{
        event->ignore();
    }
}

void MyListView::startDrag(Qt::DropActions supportedActions)
{
    QByteArray itemData;
    QDataStream dataStream(&itemData, QIODevice::WriteOnly);

    ListWidgetItem *item = dynamic_cast<ListWidgetItem *>(childAt(dragPoint));

    dataStream << dragPoint;

    QMimeData *mimeData = new QMimeData;
    mimeData->setData("application/x-QListView-DragAndDrop", itemData);

    drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->setHotSpot(mapToParent(QPoint(item->x(),y)));
    drag->setPixmap(currentPixmap);

    QModelIndex indx = indexAt(dragPoint);
    if (drag->exec(Qt::MoveAction | Qt::CopyAction) == Qt::MoveAction)
     {
        model()->removeRow(indx.row());
     }

}

我已经搜索过,但没有得到任何合适的解决方案。 谢谢

最佳答案

您看过 QAbstractItemView 的 DragDropMode 吗? https://doc.qt.io/archives/qt-4.8/qabstractitemview.html#dragDropMode-prop

听起来这就是您想要实现的目标。

关于Qt:使用拖放重新排序 ListView 项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12668797/

相关文章:

qt - Qt 中未找到 Qlistview Selectionchanged 事件?

qt - QItemDelegate 中编辑器的高度

linux - 为什么从 https 服务器下载文件在带有 montavista linux 的嵌入式设备上不起作用?

c++ - 如何将 Qt 库连接到标准 C++ 项目?

c++ - 如何在 Linux 上使用 Qt 读取 HID 设备 (/dev/hidrawX)?

javascript - 拖放并计算宽度

c++ - 使用自定义编辑器调整 QTableView 部分的大小

c++ - Qt 中的按键事件

delphi - Firemonkey 中缺少事件操作和过程

android - 重新启动时保持拖放项目的位置