Map mouse coordinates to QGraphicsScene coordinates - qt

I have a QWidget with a QGraphicsScene member. What I to do is for the QWidget to receive a mousePressEvent (by overloading) and then find a graphics item in the scene from the mouse coordinates supplied by the event.
So my question is how do I convert the mouse coordinates to graphics scene coordinates so I can compare to the graphics item?
Thanks

Use QGraphicsView::mapToScene to convert the mouse position to the coordinates system of your scene.

Related

Mouse position and a QDialog

I am trying to figure out if there is a way to make a qdialog to input the co-ordinates of a line such that the co-ordinates can be given by mouse position or a qdialog (via QLineEdit items). Is there a way to have the mouse position be displayed in the QLinedEdit items in the qdialog when moving the mouse of the canvas or move the line points when typing in the dialog?
Thanks.

Qt: How to create/render Arrow Graphics Item on QGraphicsscene

How do we create a Arrow graphics item which gets displayed on a graphics scene?
My requirement is that I drag and drop a QGraphicsLineItem from one scene to another. Once the Line item is dropped on a scene, a Arrow graphics Item should display perpendicular to the line item dropped on the scene. I should be able to display the Arrow Item on either side of the line. Currently I am able to drop a Line item onto the scene. I need source code for creation of an Arrow item.
Can somebody please help me with this scenario?
There are two possible options here. One is to have an image that you load into a QGraphicsPixmapItem and position and rotate it as desired.
The better method would be to create a class inherited from QGraphicsItem, and draw the arrow in its paint method, with the calls to drawLine.
When you inherit from QGraphicsItem, make sure that you overload the boundingRect() function, as well as the paint() function.

How to get pixel on QGraphicsPixmapItem on a QGraphicsView from a mouse click

I have a QGraphicsScene with a QGraphicsPixmapItem on it, showing an image. I also have a view showing the scene. I have a mousePressEvent() function defined, looking for mouse clicks on the view.
The view is setup to contain the pixmap:
//pixmap is a QGraphicsPixmapItem *
view->fitInView(pixmap, Qt::KeepAspectRatio);
I can get the position of a mouse click in the view's coordinate system:
//e is my QMouseEvent *
QPoint local_pt = view->mapFromGlobal(e->globalPos());
Now I'd like to map this point to the original image coordinates, using any combination of the QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
I've tried pixmap->boundingRect(), which gives me a QRectF(0,0 778x582), which has the appropriate dimensions (of the original image), but I do not see how the x and y coordinates are related to the local point of the click.
How do I get position of the mouse click in the original image coordinates?
EDIT:
This is what ultimately worked:
//e is my QMouseEvent *
QPoint local_pt = view->mapFromGlobal(e->globalPos());
QPointF img_coord_pt = view->mapToScene(local_pt);
img_coord_pt is (0,0) when I click the top left corner of the image, and (image width, image height) at the bottom right corner.
QGraphicsView::mapToScene maps screen coordinates to scene coordinates, then use QGraphicsView::itemAt to get the item and QGraphicsItem::mapFromScene to map scene global coordinates to item local coordinates.
There are inverses of these, of course.

How to get visible scene rectangle of QGraphicsView?

I'm displaying a map built as rectangle of QGraphicsPixmapitem items (each item stands for one map tile). Because my map is quite large (around 30 MB of PNG files) I want to be able to load pixmaps on demand only when they're visible for user in QGraphicsView and unload when they became invisible.
Is there any way to figure out visible scene rectangle?
This gives you the visible scene rectangle:
sceneRect = graphicsView.mapToScene(graphicsView.rect()).boundingRect()
In case there is a shear or rotation transformation present it gives you the bounding rectangle of the visible scene area. If you do not have such transformations (only shift or zoom) the returned rectangle is the exact scene area.
Now for your real problem of efficiently display a huge tiles map in a scene? You could load the tiles in background and first evaluate if your Qt framework isn't already optimized for big pixmap that are outside the visible range. 30 MB also doesn't sound so big that it wouldn't fit into memory.
QGraphicsView inherits the QWidget::geometry() function. You can use this to determine its location and size within its parent widget. (Outside of its constructor)
The QGrapicsScene can be larger than the QGraphicsView. The default QGraphicsView will add horizontal and vertical scroll bars to house the QGraphicsScene. I imagine you would like to do something like this:
//create a QGraphicsScene (for this example *scene) that is the size of your entire map.
QGraphicsScene *scene=new QGraphicsScene(0,0,mapWidth,mapHeight);
//create a QGraphicsView* named view that is the size of your visible area
//I'm assuming visibleHeight and visibleWidth do not change (this is your viewing window)
QGraphicsView *view=new QGraphicsView(0,0,visibleWidth,visibleHeight);
view->setScene(scene);
Have the user control the x and y position of the scene that triggers some custom signal like sceneMoved(int,int). Before you redraw the scene, call a slot to check the new position of the scene:
connect(this,SIGNAL(sceneMoved(int,int)),this,SLOT(drawScene(int,int)));
void SomeClass::drawScene(int newX, int newY){
//if you already have a pointer to the scene do this, or call
//QGraphicsView::scene();
int oldX=scene->geometry()->x();
int oldY=scene->geometry()->y();
//now that you have your oldX, oldY, newX, and newY, visibleWidth, visibleHeight
//you can determine what you need to redraw, what you need to delete, and what can stay
}
There is still a lot of if..else, but you get the point. I suggest trying to segment your map into squares the size of your visible area.

Using QGraphicsView to display a local map

I'm trying to use QGraphicsView in order to display a map image and draw some items on top of it. The map boundaries are in a Cartesian coordinate system, for example NE(-500,200) to SW(600,-350). I know how to map image pixels <--> my coordinate system.
I would have to achieve the following:
Add a map image to the scene and tell Qt how to map the actual image pixels to scene coordinates.
Add graphic items at their real position, e.g. (-100,200)
Doing (2) is straightforward - simply add the item to the scene. How do I achieve (1)? what should I do after I call scene->addPixmap()?
Edit - A few clarifications:
I'm mapping an indoor area of a few hundred meters
The map will change at real-time in two ways:
The map gets bigger every few seconds
The graphic items move, change colors, etc.
Put the pixmap into a QGraphicsPixmapItem and place it in the scene.
Call setScale() to map the QGraphicsPixmapItem so 1 meter maps to 1 unit in the scene coordinate. ie. setScale(0.1) if 10 pixels in the pixmap equal 1 meter.
Update the pixmap and scale of the item as needed.
Call fitInView() to zoom to the pixmap.
Place other graphic items in the scene. Treat the units of the scene coordinate as meters.
...
Profit! :)

Resources