PDA

View Full Version : Create a graphics item on mouse press and put it directly into drag/move mode



ghorwin
29th August 2019, 13:57
Hi all,

I have a graphics view and I want a fairly simple feature. When I click on a graphics item I want to create a new movable graphics item and want this item to be moved directly.

Right now, I have implemented the mousePressEvent() and create the new item. But I always need to click a second time (and hold the mouse button and move), in order to get a call to itemChanged() with QGraphicsItem::ItemPositionChange.

How can I get the QGraphicsView framework to recognize the currently pressed mouse button as start of a drag operation on the new item?

Thanks,
Andreas

d_stranz
29th August 2019, 16:41
I think your problem is that when the mouse button goes down, there is no graphics item present yet, so the scene / view has no currently selected item. Perhaps you need to add some code to select the item immediately after creating it.

ghorwin
2nd September 2019, 09:13
Selecting the item is easy, but I want the item to be marked by the framework as "started a drag operation" so subsequent mouse movements will make the graphics scene send the itemChanged() event with type QGraphicsItem::ItemPositionChange.

My best bet is to create and emit a new graphics view "mouse pressed" event. But currently that doesn't seem to cause anything. Maybe I need to use a QTimer::singleshot(), so that the last event gets completed before sending the new?

Any ideas?

ghorwin
2nd September 2019, 14:29
Update: I have tried two things without avail:

1. after creating the object calling "grabMouse()" on the object (still within the QGraphicsScene::mousePressEvent() event handler function). Does not work because base class implementation ungrabs the item right away.

2. sending an own MousePressEvent to the graphics view using the following code:




QGraphicsView* view = views()[0];
QPointF ptScene = mouseEvent->pos(); // mouseEvent->pos() holds the current position that the user clicked on
// Note: the newly created item has a boundingRect() that encloses this position.
QPoint ptView = view->mapFromScene(ptScene);
QPoint ptGlobal = view->viewport()->mapToGlobal(ptView);

QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMousePress);
event2.setScenePos(ptScene);
event2.setPos(ptScene);
event2.setScreenPos(ptGlobal);
event2.setButton(Qt::LeftButton);
event2.setButtons(Qt::LeftButton);
event2.setModifiers(QApplication::keyboardModifier s());

qApp->sendEvent(view, &event2); // strange: does not call the QGraphicsScene::mousePressEvent() function again!


So, in variant 2, maybe the mouse press event object is not fully configured? Behavior does not change if I delay sending the event by a timer.

Problem remains: creating an object on click and putting it into drag mode right away...???

Added after 21 minutes:

Solved:

1. create new item
2. set flags: setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
3. add to scene
4. call grabMouse() on newly created item

Do not send another event!

This appears to work.

Note: you may call setSelected(true) when creating the item as well. However, on first move the item will get selected anyway.

d_stranz
2nd September 2019, 16:53
This appears to work.

Great, glad you solved it. Thanks for posting your solution - this will certainly help others. I will probably be doing something similar soon, so it is good to have this to refer to.