I'm writing a Qt app that is based around a QGraphicsScene
canvas with movable shapes on it, and I'm trying to integrate undo-redo functionality. For most functions like creation and deletion of shapes it's fairly trivial to implement on the QGraphicsScene
itself, but I want elements to be movable and for the movement to be undoable. Right now I'm using the rubber band dragmode on the scene and the ItemIsSelectable
and ItemIsMovable
flags on the items. The problem is that there seems to be no good place to create the QUndoCommand
to represent shape movement. If I do it within the QGraphicsScene::itemChange
method, then selecting and moving two or more shapes results in separate undo commands for different objects being interleaved and thus are not able to be merged, so undoing results in unexpected behaviour. There's no event in the QGraphicsScene
that gets called when its items are moved around that I can see, so I'm kind of stuck.
The worst case scenario that I see is that I disable the ItemIsMovable
flag on my custom QGraphicsItem
objects and handle movement entirely in the QGraphicsScene
mouse events, but reimplementing that functionality properly seems quite complicated (I checked how Qt does it internally and there is quite a lot of code for handling complicated cases, such as where an object and some of its children are both selected). This seems like the most obvious of use cases for the undo stack (so much so that the example program for the undo framework is a QGraphicsScene
program much like mine, except without multiple object movement support) so it seems weird that there's no built-in way to do it without reimplementing a significant part of the core functionality. Does anyone have any insights or examples of programs that do this?
I solved this somewhat hackishly I think. I added a preMovePoint
property to my custom shapes and in the mousePressedEvent
of the QGraphicsScene
, I set the preMovePoint
of each of the selected shapes to their respective current positions, and in mouseReleaseEvent
, created a composite move command from the preMovePoint
to the current pos
of each shape. I would still be interested in knowing if there's a better way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With