QGraphicsItem - Follow the mouse cursor - qt

I'm stuck on how to approach this. I have a QGraphicsItem within a scene, and I'm passing a hover event from the scene to this child. While the move event occurs (I'm just using mouseMoveEvent with mouse tracking on), I want another QGraphicsItem to follow the cursor.
I don't need any collision detection, drag and drop, etc. Just an item that follows the cursor. The only two ways I can think of are...
While the mouse moves, draw a new QGraphicsItem at the mouse position. I would need to clear the scene, redraw everything, and draw the new position on top.
Somehow use the animation framework and whenever the mouse moves, animate the QGraphicsItem to move to the new mouse position in 1 millisecond.
I'm probably either overthinking this or unaware of another way to do this... any suggestions?

I did it like this
Create the GraphicsItem cursor which will be moved with mouse-cursor, and store its pointer somewhere (in scene subclass for instance. I have a toolset, so for me it's in one of these tools)
Set its Z-Value (QGraphicsItem::setZValue) so that the cursor will be painted above all other items in your scene
Track QGraphicsScene::mouseMoveEvent events, forward these events down to the cursor pointer, and update item's position
that's it.
I guess it corresponds to your solution 1, except you don't have to clear the scene thanks to z-value feature.

Related

expand qgraphicsrectitem to cover complete scene and expand all children's in same proportion

I have created a QGraphicsView with a scene set on it with QGraphicsRectItem in it.
[fig-1]
I want that when I double click on the green rectangle marked with thick black border, the scene gets filled with only this rectangle and all its children also get expanded in same proportion.
So, when I double click , I should see something like this in complete view:
I have handled the double click event but do not know how to handle this.
Also, when I double click again, I get back to the previous state (as shown in fig-1)
As the documentation states for QGraphicsView::fitInView
Ensures that item fits tightly inside the view, scaling the view according to aspectRatioMode.
So, assuming pView is your QGraphicsViewand thisis the rectangle you want to view, call fitInView from the overloaded double click event of QGraphicsRectItem: -
pView->fitInView(this);
Based on the comments that only the rect and its children should be visible, one option to guarantee this would be, on double-click, to create a separate scene, move the rect to the new scene and switch the view to the new scene.

Shadow Effects with QGraphicsRectItem in Qt

I have a QGraphicsRectItem over a scene. I intend to drag and drop this window over the scene. When the rect item reaches the left boundary end I have to show it appearing from the right end. Currently I am using two objects and hiding and showing them by calculating the boundary of scene which involves lot of calculations.
Is there any better way to achieve the same effect using just a single object?
Thank You
You could use a single item that spans the entire scene, and draw the rectangle (or 2 parts of it) in it's paint method.
But then you would lose the optimization of the BSP tree, your item would redraw even if some unrelated area repaints. If this is just 1 item, I guess it would not have much impact.
You would need to implement your own dragging with mousemove event and the like, though this is not much code, you just need to get it right.

Drop event gets disabled on QGraphicsScene

I have a QGraphicsScene. I have a video running on the scene. On top of video I add a zooming window which is a QGraphicsItem. I drag and drop this window using drag events of QGraphicsScene. This works fine.
I have to show the scene co ordinates everytime the mouse moves. For this I use a QGraphicsTextItem in MouseMoveEvent of graphics scene. The problem is when I write the MouseMoveEvent the drag and drop events stop responding.
Why does this happen?
Thank You
You likely forgot to call the base class's method:
void MyScene::mouseMoveEvent(QGraphicsSceneMouseEvent * ev) {
QGraphicsScene::mouseMoveEvent(ev);
// do your own processing
}
Another possible factor is your coordinate item being in the way of the drop - you could simply move it down a pixel or two so that it's below the mouse pointer's hot spot.

qt get scrollview position

I have a QGraphicsView inside a Horizontal Layout. The QGraphicsScene contained in the QGraphics scene is pretty large (thousands of pixels), so scroll bars show up by default to allow me to scroll through the view.
Every time I update the scene inside the graphics scene, I delete the old scene, make a new one, populate it with objects, and call view->setScene(scene). When I do this, however, the scroll bars default to the top left corner of the QGraphicsView, instead of staying where they were at.
I tried saving the QGraphicsScene::sceneRect before destroying the scene, then doing a setSceneRect() afterwards to restore it, but that doesn't work since that only affects the scene itself, not the QGraphicsView that's displaying it. I also tried to do view->verticalScrollBar()->setValue(), but that doesn't appear to affect the scroll bars at all.
How can I access the scroll bars that are created for me by default, and set them to a value that was stored earlier?
Fixed by not deleting previous scene until after the new one is set.
e.g.
QGraphicsScene *previousScene = scene;
scene = new QGraphicsScene(0, 0, levelPlist.value("level_width").toInt(), levelPlist.value("level_height").toInt());
// config scene
QGraphicsView *view = ui->graphicsView;
view->setScene(scene);
delete previousScene;
Before I give a possible solution, I would highly recommend an approach that doesn't involve destroying your scene. If you're just clear()'ing your scene, you should be able to call setSceneRect() before clearing it, which will prevent the scene from automatically resizing its rect. When it's repopulated you can call setSceneRect() with a default-constructed QRect to give it control over the size of the rect once again.
If you really need to save/restore the scroll bars as stated, the following approach has worked for me in the past:
I've had to do something similar (for different reasons), and the best solution I've come up involves doing something like this:
Before clearing the scene, save off the positions of your vertical and horizontal scrollbars
Before reconstructing the scene, connect to the QScrollBar::rangeChanged() signal with a queued signal/slot connection. This signal should get fired after you've repopulated your scene, and it indicates that the scroll bars have been reconfigured by the view.
In your slot, disconnect from the rangeChanged() signal, and restore the scroll bar positions
Note that this is pretty much guaranteed to cause some flicker/jumpiness.

QGraphicsView - how to disable mouse and keyboard scrolling

In my application I have QGraphicsScene with pixmap added and all is viewed in QGraphicsView with scrollbars off.
The program window is smaller then pixmap and when I press arrow keys or move mouse wheel the pixmap is being moved.
How do I disable that so even if the pixmap is bigger than window it won't be moved by keyboard or mouse unless I use my events for that?
(I tried to set interactive property to false but that didn't work)
I believe the easiest solution would be to set FocusPolicy of QGraphicsView to NoFocus and then process all key events in main window.
ui->graphicsView->setFocusPolicy( Qt::NoFocus );
I think the easy way is to use QGraphicsView::setSceneRect() to set the area that the view is allowed to visualize.
If you set the view's sceneRect() to the actual size of the view widget (or just slightly smaller), then it won't be able to scroll or pan outside of this rectangle.
I don't know if there's an easier way, but the moderately easy way would be to make a class that inherits your QGraphicsView class, and overrides the mouse and key press events.
The harder way would involve installing an event filter on the widget.
In my opinion, the hardest brute-force solution would be to detect the change through some sort of signal, and set it back to how it was.

Resources