Overlaying image within larger image using QGraphicsView or QGraphicsScene - c++

I'm new to Qt, so I might mangle this question. Having said that-
I'm rendering an image within a subclassed QGraphicsView. I added the image to the scene as a Pixmap with addPixmap(). I'd like to overlay (blit) smaller images on top of the larger one in specific locations. I can add the smaller image to the scene as well by again calling addPixmap(), but it always displays in the upper left corner. I'd like to set those coordinates myself.
How can I accomplish this?
Thanks!

QGraphicsScene::addPixmap returns a pointer to the added QGraphicsPixmapItem. If you want to set its position, you can do something like this:
QGraphicsPixmapItem *item = scene->addPixmap(yourPixmap);
item->setPos(50, 50); // sets position to scene coordinate (50, 50)
If you want to overlay images on top of other images, make sure you know about z-values. See the QGraphicsItem documentation for details. Basically, the z-value determines the stacking order.
Lastly, familiarize yourself with parenting of QGraphicsItems. When a QGraphicsItem has a parent item, it means (among other things) that its coordinates are expressed in terms of its parents' coordinates. So if an item has a position of (0, 0), but it's the child of an item whose scene position is (50, 50), then the child item will be displayed at (50, 50). So, given the above example, you could then do:
QGraphicsPixmapItem *childItem = new QGraphicsPixmapItem(item);
This creates a new item, "childItem", whose parent is "item". Its coordinates are (0, 0), because they haven't been set yet, but its scene coordinates are (50, 50), because it is the child of "item". Note that when you specify an item's parent, you don't need to add the child item to the scene; it is implicitly added.

Related

QTabWidget with QGraphicsView

I have a QTabWidget and second page containing a QGraphicsView with scene. The scene canvas is larger than the QGraphicsView's viewport and I'm using QScrollBar to move objects on the scene.
On the scene I place a lot of QGraphicsItem objects. I have a horizontal and a vertical scroll bar, and some items can move only horizontally, another objects on scene can move only vertically.
My QGraphicsview coordinates start at the top left corner of QGraphicsview. After moving objects on the scene, if I change the page of the QTabWidget from second page to first and then back again, the start of coordinates is moved to the center of QGraphicsView, and all objects on the scene are moved to new positions automatically.
This happens only when I'm using a QTabWidget, if I change the parent of QGraphicsView to QWidget, all works well.
I found a solution. Just need to calculate rect of the scene, and set obviously using QGraphicsScene::setSceneRect() method. Otherwise, position of my scene in the QGraphicsView may surprise.

QGraphicsScene image pos pixmap

I am using Qt Graphics Framework for displaying an image. I have opened a raw image in subclassed QGraphicsScene in QGraphicsView using addPixmap(). I have added zoom feature by using scale function and drag mode is set as scroll hand drag. Now, I need to get the pixel coordinates within the scene on mouse hover such that the x and y value show the pixel in the image (drawn by pixmap) the mouse is currently pointing to. I tried using pos() but it didn't work.
Here is the code from Widget.cpp:
img = openImage(dirPath2.toLocal8Bit().data(),
sizeX,sizeY,file_heade,scan_heade,bpp,sign);
QPixmap x = QPixmap(sizeX,sizeY);
x.convertFromImage(img,Qt::AutoColor);
scene->addPixmap(x);
ui->disp_img->setDragMode(QGraphicsView::ScrollHandDrag);
GraphicsScene.h:
class GraphicsScene : public QGraphicsScene {
public:
GraphicsScene(QWidget *parent) : QGraphicsScene(parent){}
};
(preferably the pixmap coordinates but even that doesn't happen and if the values change when zoomed I will use scale factor to get the original values)
I suggest you start by reading about Qt's Graphics Coordinate System.
There are various layers of coordinate systems and you need to think about those with which you dealing with. At the top layer is the screen (or view), which is where the mouse coordinates reside.
The next layer from the view is the graphics scene. Graphics items, such as the QGraphicsPixmapItem which you added with addPixmap, reside here. The graphics scene can be visualised as a world of items, each with there own position and orientation.
Moving to the last coordinate system is an item's local coordinate system. If, for example, we take a rectangle, it may have local coordinates of (-5, -5, 10, 10) for (x, y, w, h). This item is then placed in the scene at some position. If its position is the origin of the scene (0,0), then the item's local coordinates would read the same as its scene coordinates.
However, if we move the rectangle +5 units in x-axis, its local coordinates are the same, but its scene coordinates would now be (0, -5, 10, 10).
Likewise, the view (QGraphicsScene) is a window into the scene and can be looking at the whole scene, or just part of it. As the view's top left coordinate is (0,0), it may map onto (0,0) of the scene, or may not, depending on what area of the scene the view is looking at.
So, by getting a mouse position you're starting in the view's coordinates and need to convert to the scene's coordinate system. Fortunately, Qt provides lots of useful functions for this at every level.
To convert the mouse coordinates from the view to the scene, you can use the view's mapToScene function.
Using the scene coordinates you can then get an item and map that to the local coordinate's of the item with the item's mapFromScene.

QGraphicsView and QGraphicsScene coordinate systems

in Qt 4.8 i have create a QGraphicsView and a DynamicRadarScene(derived from QGraphicsScene):
QGraphicsView* view = new QGraphicsView;
view->setMinimumSize(800, 600);
DynamicRadarScene* _scene = new DynamicRadarScene(mode, channel_types, this);
view->setScene(_scene);
What is the coordinate system of QGraphicsScene? (0,0) is from upper left corner?
How can i draw an item in the upper right corner of the scene (i have set it 800x600: view->setMinimumSize(800, 600);)?
If i resize the widget and so i resize the QGraphicsView, how can move the item i have drawn before to remain in the upper left corner?
Yes, the upper left corner is generally the coordinate of (0,0) in a graphics scene. What you need to consider is that a QGraphicsView is like a window looking into a world (the QGraphicsScene). You set the view to look at an area or the scene, which may be all or just part of the scene.
Once the scene and view are setup, you can then add QGraphicsItems / QGraphicsObjects or instances of classes derived from those by using functions such as QGraphicsScene::addItem. These items are positioned in the scene and draw themselves.
i (sic) resize the widget and so i resize the QGraphicsView
You can change the QGraphicsView position and dimensions, but then the items in the scene will remain in the same place within the scene. Usually you would set up the scene and view and then move / resize the graphics items / objects within the scene, often with the setPos function: QGraphicsItem::setPos(). This sets the position of the item, relative to its parent. If the item has no parent, it sets the position of the item in the scene.
QGraphicsScene has property sceneRect. If it is not set then it is auto adjusted depending on scene content. This can give a filling that origin of coordinating is in some strange place or even that it is mobile.
Set this property. See also this.

Qt QGraphicsScene origin point

Whenever I add a new item to a QGraphicsScene, the origin of the QGraphicsScene seem to change for the position of the item I have just added.
How to make the QGraphicsScene origin fixed?
Do I need to add the item first in the QGraphicsScene and then specify a position for the item?
Well, by default the content of the scene will be centered in the QGraphicsView. The origin of the graphics scene does not change randomly.
You might want to use setSceneRect() to define the size of the scene, so that the QGraphicsView always centers the scene in the view in a fixed manner. (If you don't set it manually, the rect will be calculated based on the items in the scene, which changes if you add more.)
I answered a related question about a year ago that may be helpful:
How to draw a point (on mouseclick) on a QGraphicsScene?
Ditto to what badcat.
There are a lot of controls for adjusting or manipulating your viewport(s) that you have pointing at your scene. The scene sets what is on the stage. The view is how you look at it. Be sure to set the sceneRect or set it indirectly using centerOn or fitInView or scale or translate from the QGraphicsView class.
http://qt-project.org/doc/qt-4.8/graphicsview.html
http://qt-project.org/doc/qt-4.8/qgraphicsview.html
QGraphicsScene::setSceneRect ( const QRectF & rect ) will make it absolute.
see http://doc.qt.digia.com/qt/qgraphicsscene.html#sceneRect-prop

Why do the first added item always appear at the center in a graphics scene/view in Qt?

I have a graphics scene and view, and then I'm adding a single element. But no matter what x/y coordinate I give, it always appears at the center of the graphics view.
Why does this happen, and how can I make it appear at, say, the upper left corner?
This is my code:
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
QGraphicsEllipseItem *ellipseItem = scene->addEllipse(150, 150, 10, 10);
The reason for this is that by default, QGraphicsScene computes its sceneRect by adding all the item rectangles together. When you add the first item, it automatically uses it as the scene rect. And by default QGraphicsView scales and centers on the scene rect.
If you know the final or desired scene rect, set it before you add any item:
scene->setSceneRect(0, 0, 800, 600);
scene->addEllipse(150, 150, 10, 10);
You probably want to define a scene-rectangle that is shown by the QGraphicsView. I think the default view just shows the centered bounding rectangle of the current scene, which is just your ellipse. You can use QGraphicsView::fitInView to define the area to be shown explicitly.