Drop event gets disabled on QGraphicsScene - qt

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.

Related

How to display a thumbnail on QGraphicsScene?

First, I draw a lot of QGraphicsItems on the QGraphicsScene. I want to show a thumbnail that can be dragged freely in the bottom right corner of the QGraphicsScene. What classes should I use? How do I use them?
Try to capture Mouse events on QGraphicsItems
Option 1 : using mousemove calculated delta from older position to new and move your graphicsItem Accordingly.
Option 2 : check QgraphicsItem support for drag events or not
Check here Qt: qgraphicsitem drag and drop

How are mouse events propagated in QGraphicsView, scene and item?

I have a QGraphicsView on which there is a QGraphicsScene on which there are QGraphicsRectItem.
For each of these 3 classes, I've implemented mousePressEvent().
Now, I would want to know what happens when we click. Does the event first go to view, then to scene, then to item?
Can you please explain in detail about how mouse clicks are handled for each of these 3 classes?
I have already implemented eventFilter for QGraphicsView to support zoom and pan functionalities.
Example:
In the image below, I would want to get the innermost green rectangle (with text 230, 30) when I click on it...

How can I prevent a QWidget from painting, but still respond to events?

I have a QGLWidget that renders an OpenGL scene inside a Qt application. I would like to add some other translucent Qt widgets that are overlaid on top of the QGLWidget. This is more difficult than with standard widgets since the OpenGL drawing context is unknown to Qt's painter classes. So, if I just do the obvious thing and place a transparent toolbar on top of the QGLWidget for instance, the transparent part of the toolbar instead renders black (it doesn't have access to the OpenGL frame buffer when painting).
It seems that the recommended way for handling this sort of thing is to overpaint the 2D content after drawing the OpenGL scene. The linked example seems very straightforward, as long as you're just drawing simple shapes. Instead, what I would like to do is to defer the painting of some child QWidget objects to be done inside the paint event for the QGLWidget.
So, my problem boils down to this:
Prevent the overlay QWidgets from painting in the normal, 2D context.
In the paint event handler for the QGLWidget, paint the overlays after painting the 3D scene that makes up the background.
The second item on this list seems to be simple: I can use QWidget::render() inside the QGLWidget's paint event to draw the desired widgets on top of the viewport. This works just fine.
The first item is more tricky: I need a way to prevent the widgets from painting during the normal course of events and only paint them in the QGLWidget's paint handler. One obvious way to do this is to hide the overlays using QWidget::hide(). This does allow me to paint the widgets atop the OpenGL scene as I would like. However, since the widgets are hidden, they do not respond to mouse or keyboard events. As an example, I'm using a QToolBar with a few buttons on it, and the toolbar is painted properly, but is non-functional (none of the buttons respond to clicks). So, if going down this path, it seems that I would need a way to force the widget to still respond to events even though it is hidden.
Another approach that I've tried is to intercept the QToolBar's paint event using an event filter, with the goal of preventing the toolbar from painting itself. However, the toolbar is still rendered; I'm assuming that this is because the various buttons on the toolbar are child widgets that are still painted, even if I intercept the parent's paint event.
Any ideas on a way that I could accomplish my goal?
I don't understand your issue completely, but I'll try to answer the question stated in the title. You should use event filters. Install an event filter using widget->installEventFilter(object), where widget is a widget you want to block painting, and object is an object of any of your QObject-derived classes. Reimplement eventFilter of this class:
bool MyClass::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::Paint) { return true; }
return false;
}
When you return true from your eventFilter, the event is filtered and paint doesn't occur.
You can also try to use widget->setUpdatesEnabled(false) to temporarily disable painting. Don't forget to re-enable it when you're done.

QGraphicsItem - Follow the mouse cursor

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.

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