drag and drop detect source of drag fails
-
I have a class
Room
which holds connections to three neighborRoom
s.class Room : public QGraphicsWidget { Q_OBJECT //.... private: static constexpr auto mCountOfNeigbours = 3; std::array<Room *, mCountOfNeigbours> mNeigbours;
No i want to drag and drop the player from one room to another. But only to the neighbour
Room
s.So i start a drag like this:
void Room::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton)) .length() < QApplication::startDragDistance()) { return; } setPlayer(false); auto drag = new QDrag(event->widget()); auto mime = new QMimeData; drag->setMimeData(mime); mime->setImageData(playerDraggedImage()); drag->setPixmap(QPixmap::fromImage(playerDraggedImage())); drag->setHotSpot(QPoint(0, 0)); auto result = drag->exec(); if (result == Qt::IgnoreAction) { setPlayer(true); } setCursor(Qt::OpenHandCursor); }
The dragEnterEvent and the
dropEvent
which should get executed on a neigbour look like this:void Room::dragEnterEvent(QGraphicsSceneDragDropEvent *event) { if ((event->mimeData()->imageData() == playerDraggedImage()) && isNeighbour(event)) { event->setAccepted(true); } else { event->setAccepted(false); } }
void Room::dropEvent(QGraphicsSceneDragDropEvent *event) { if ((event->mimeData()->imageData() == playerDraggedImage()) && isNeighbour(event)) { setPlayer(true); } update(); }
With a helper which checks if the room is a neigbour of the source room were the drag started:
bool Room::isNeighbour(QGraphicsSceneDragDropEvent *event) const { auto room = qobject_cast<Room *>(event->source()); if (room == nullptr) { return false; } for(const auto &neighbour : mNeigbours) { if (room == neighbour) { return true; } } return false; }
So far so good but it is not working. If i try to find the sender of the drag with
auto room = qobject_cast<Room *>(event->source());
The result is always zero.
However i can see were i make the drag:
auto drag = new QDrag(event->widget());
Here
event->widget()
has a address, Then why it arrives withnullptr
on the target? -
@sandro4912 said in drag and drop detect source of drag fails:
Here event->widget() has a address
But is this widget a Room*?
qobject_cast<Room >(event->source()); will return nullptr if event->source() is not a Room -
The
Room
s get put into aQGraphicsScene
but i would have expect thatQGraphicsSceneMouseEvent *event->widget()
is aRoom
inRoom::mouseMoveEvent
I added the accept like this:
void Room::dropEvent(QGraphicsSceneDragDropEvent *event) { if ((event->mimeData()->imageData() == playerDraggedImage()) && isNeighbour(event)) { setPlayer(true); update(); event->setAccepted(true); } else { event->setAccepted(false); } }
Is it maybe impossible like i think? Do i have to sublass
QMimeData
and pass thepointer
of the object were thedrag
was created? -
@sandro4912 said in drag and drop detect source of drag fails:
QGraphicsSceneMouseEvent *event->widget()
So did you actually check it?
Returns the widget where the event originated,
I would not expect that a mouse move event's originator is a room object.
-
@sandro4912 said in drag and drop detect source of drag fails:
Is it maybe impossible like i think? Do i have to sublass QMimeData and pass the pointer of the object were the drag was created?
Yes i checked it and it is not a `Room. I guess i thought it wrongt. So to shorten my question.
How can you tell in a drop event were the drag was started from?
Making a custom
QMimeData
type and passing the Room pointer ? -
That's one way yes.
-
I solved the issue the pragmatic way:
class RoomMimeData : public QMimeData { Q_OBJECT public: void setRoom(Room *room); Room *room() const; private: Room *mRoom; };
void Room::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { //... auto drag = new QDrag(event->widget()); auto mime = new RoomMimeData; mime->setRoom(this); drag->setMimeData(mime); //.. }
void Room::dropEvent(QGraphicsSceneDragDropEvent *event) { const auto roomData = qobject_cast<const RoomMimeData *>(event->mimeData()); if(roomData && isNeighbour(roomData->room()) && roomData->imageData() == playerDraggedImage()) { enter(); update(); event->setAccepted(true); } else { event->setAccepted(false); } }