Qt - 如何在拖动项目时显示图像/图标/数据?

时间:2018-05-10 18:40:41

标签: c++ qt qt5

我有一个应用程序,我可以将项目拖动到QGraphicsScene并根据项目文本创建一个新对象,但如何在项目移动时更改显示的数据?

例如,我想显示一个图标而不是文字:

enter image description here

我有一些包含itens的列表:

OptionList::OptionList(QWidget *parent) : QListWidget(parent)
{
    this->setDragEnabled(true);
    this->setDropIndicatorShown(true);
    this->setSelectionMode(QAbstractItemView::SingleSelection);
    this->setDefaultDropAction(Qt::CopyAction);
    this->setViewMode(QListView::ListMode);

    for(const QString &color : {"Blue", "Red", "Green", "Yellow"})
    {
        OptionItem *item = new OptionItem;
        item->setText(color);
        item->setFlags(Qt::ItemIsEnabled| Qt::ItemIsSelectable| Qt::ItemIsDragEnabled);
        addItem(item);
    }
}

我将itens放入场景中以创建一个新对象:

MyScene::MyScene()
{
    setBackgroundBrush(Qt::lightGray);
}

void MyScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
    if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    event->setAccepted(true);
}

void MyScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
    if(event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
    event->setAccepted(true);
}

void MyScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    QByteArray encoded = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
    QDataStream stream(&encoded, QIODevice::ReadOnly);

    QStringList colors;

    while (!stream.atEnd())
    {
        int row, col;
        QMap<int,  QVariant> roleDataMap;
        stream >> row >> col >> roleDataMap;
        colors << roleDataMap[Qt::DisplayRole].toString();
    }

    QPointF posView = event->scenePos() ;

    for(const QString & color: colors)
    {
        Block *newBlock = new Block(color);
        newBlock->setPos(posView);
        addItem(newBlock);
    }
}

然后,我创建了从QListWidgetItem派生的OptionItem类,并重新实现了mousePressEvent,mouseMoveEvent和mouseReleaseEvent

OptionItem::OptionItem()
{

}

void OptionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    event->setAccepted(true);
}

void OptionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QDrag *drag = new QDrag(event->widget());

    QMimeData *mime = new QMimeData;

    QImage image(":/images/MyIcon_icon.png");
    mime->setImageData(image);

    drag->setMimeData(mime);
    drag->setPixmap(QPixmap::fromImage(image));
    drag->setHotSpot(QPoint(15, 30));

    drag->exec();

    event->setAccepted(true);
}

void OptionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    event->setAccepted(true);
}

我试图在Qt Creator中关注拖放机器人示例,但它不是同一件事

当我开始拖动项目

时,似乎图像显得很快

有没有办法在整个操作中拖动项目时显示图标?

2 个答案:

答案 0 :(得分:0)

QAbstractItemView继承的类支持默认拖动,因此它们已经实现了方法,而您指出的示例显示了如何为某些没有它的类实现此功能,在您的情况下的任务很简单,您必须覆盖startDrag的方法QListWidget

<强> optionilist.h

#ifndef OPTIONLIST_H
#define OPTIONLIST_H

#include <QListWidget>


class OptionList: public QListWidget{
public:
    OptionList(QWidget* parent=nullptr);

protected:
    void startDrag(Qt::DropActions supportedActions);
};

#endif // OPTIONLIST_H

<强> optionlist.cpp

#include "optionlist.h"

#include <QDrag>

OptionList::OptionList(QWidget *parent): QListWidget(parent){

    setDragEnabled(true);
    setDropIndicatorShown(true);
    setSelectionMode(QAbstractItemView::SingleSelection);
    setDefaultDropAction(Qt::CopyAction);
    setViewMode(QListView::ListMode);

    for(const QString &color : {"Blue", "Red", "Green", "Yellow"}){
        QListWidgetItem *blue = new QListWidgetItem;
        blue->setText(color);
        blue->setFlags(Qt::ItemIsEnabled| Qt::ItemIsSelectable| Qt::ItemIsDragEnabled);
        addItem(blue);
    }
}

void OptionList::startDrag(Qt::DropActions supportedActions){
    if(supportedActions & Qt::CopyAction){
        QList<QListWidgetItem *> m_items = selectedItems();
        if(m_items.isEmpty())
            return;
        QMimeData *data = mimeData(m_items);
        QDrag *drag = new QDrag(this);
        QPixmap pixmap(":/images/MyIcon_icon.png");
        drag->setPixmap(pixmap);
        drag->setMimeData(data);
        drag->setHotSpot(pixmap.rect().center());
        drag->exec(Qt::CopyAction);
    }
    else
        QListWidget::startDrag(supportedActions);

}

可以在以下link找到完整的代码。

答案 1 :(得分:0)

以上是正确的!

还应注意,drag->setMimeData(data);之后需要调用drag->setPixmap(pixmap);

否则,在拖动过程中,它将显示原始的mimedata类型,而不显示图像/图标。