Reputation: 119
I have an application where I can drag an item to a QGraphicsScene and create a new object depending on the item text, but how can I change the data being displayed while moving around the item?
for example, instead of a text, I want to show an icon:
I have a list with some 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);
}
}
I drop the itens into the scene to create a new object:
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);
}
}
Then, I created OptionItem class, derived from QListWidgetItem, and reimplemented the mousePressEvent, mouseMoveEvent and 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);
}
I tried to follow the drag drop robot example in the Qt Creator but it isn't the same thing
It seems that the image appears very quickly when I start dragging an item
Is there a way to show the icon while dragging the item through the whole operation?
Upvotes: 1
Views: 2593
Reputation: 1254
The above is correct!
Also should note that drag->setMimeData(data);
needs to be called after drag->setPixmap(pixmap);
.
Otherwise, during the drag moving, it will show the original mimedata type instead of showing an image/icon.
Upvotes: 0
Reputation: 243907
The classes that inherit from QAbstractItemView
support the default drag so they already have implemented methods, instead the example you point out shows how to implement this functionality for some class that does not have it, the task in your case is simple, you must overwrite the method startDrag
of 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);
}
The complete code can be found at the following link.
Upvotes: 2