[QGraphicsScene] Drag'n'Drop in mouseMoveEvent() starten

Alles rund um die Programmierung mit Qt
Antworten
bingo
Beiträge: 1
Registriert: 30. Juli 2013 02:21

[QGraphicsScene] Drag'n'Drop in mouseMoveEvent() starten

Beitrag von bingo »

Hallo liebe Community!

Wie startet man einen Drag'n'Drop-Vorgang korrekt aus der mouseMoveEvent()-Methode einer QGraphicsScene heraus?

Mein Ziel:
Ich möchte zusätzlich zum normalen Verschieben der Items die Möglichkeit von echtem Drag and Drop in meine Graphics-Scene einbauen.
Immer wenn ein Item über ein anderes Item gezogen wird, und dieses "Drop" unterstützt, lege ich also ein QDrag-Element an und rufe exec(...) auf.

Problem:
Wenn man QDrag::exec() in mouseMoveEvent() bei gedrückter Maustaste aufruft, wird QGraphicsScene::mouseReleaseEvent() nicht mehr ausgeführt, was anscheinend innerhalb QT zu einem ungültigen Zustand führt (das nächste Item kann nicht normal verschoben werden, sondern springt an eine falsche Position). Vielleicht ist das allerdings auch ein Feature und man darf QDrag so nicht verwenden.

Minimales Beispiel:

Code: Alles auswählen

#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>
#include <QMimeData>
#include <QDrag>

class Scene : public QGraphicsScene {
public:
	Scene() {
		QGraphicsRectItem* item;

		// add first item
		item = new QGraphicsRectItem();
		item->setRect(0, 0, 20, 20);
		item->setBrush(Qt::red);
		item->setFlag(QGraphicsItem::ItemIsSelectable);
		item->setFlag(QGraphicsItem::ItemIsMovable);
		item->setPos(40, 40);
		addItem(item);

		// add second item
		item = new QGraphicsRectItem();
		item->setRect(0, 0, 20, 20);
		item->setBrush(Qt::blue);
		item->setFlag(QGraphicsItem::ItemIsSelectable);
		item->setFlag(QGraphicsItem::ItemIsMovable);
		item->setPos(20, 60);
		addItem(item);
	}
	virtual ~Scene() {
	}
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) {
    	QGraphicsScene::mousePressEvent(event);
    }
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
    	QGraphicsScene::mouseMoveEvent(event);

    	if (event->buttons() != 0 && event->modifiers() != 0) {
    		// perform drag
    		QMimeData* mimeData = new QMimeData();
    		QDrag* drag = new QDrag(event->widget());
    		drag->setMimeData(mimeData);
    		drag->exec();
    	}
    }

};

int main(int argc, char* argv[]) {
	QApplication app(argc, argv);

	Scene* scene = new Scene();

	QGraphicsView* view = new QGraphicsView(scene);
	view->setAcceptDrops(true);
	view->setDragMode(QGraphicsView::RubberBandDrag);
	view->setAlignment(Qt::AlignCenter);
	view->setMouseTracking(true);
	view->show();

	return app.exec();
}
In dem Beispielprogramm kann man zwei Rechtecke verschieben. Der Fehler tritt auf, wenn man ein Rechteck verschiebt, dann CTRL drückt, um QDrag::exec() aufzurufen, es fallenlässt, und danach dasselbe (oder das andere) anklickt und dieses erneut verschiebt. Das zuletzt verschobene Rechteck springt nun unmittelbar zurück zur Ursprungsposition vor dem ersten Verschieben (bzw. springt zum Ursprung der Scene).

Mache ich etwas falsch? Oder sollte es prinzipiell so eigentlich funktionieren?

Vielen Dank für Eure Hilfe!
Ingo
Antworten