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.
Related
event->scenePosition().x();
event->scenePosition().y();
This way I can only get the current position of the cursor on the widget. It just tells me what position on the screen I clicked. I want to get the actual location of the widget when I scroll or zoom the widget.
I made a mathematical formula to get the actual position when zoomed in , zoomed out or scrolled the widget and was manipulating the screen coordinates according to scaling and scrolling , but this was not giving me high precision. Are there special functions for this in Qt?
I want to place an item (foreground) above another item (background) at a certain coordinate (x, y) of the background. The background is
transformed and foreground and background are in no parent-child relation.
I thus would do:
foreground->setPos(foreground->mapToParent(
foreground->mapFromScene(background->mapToScene(x, y))))
First determine where on the scene the background coordinate will be after transformation of the background, then map this coord from the scene to the foreground item's parent coordinate system for the setPos() call.
However this seems to be equivalent (at least in my case) to:
foreground->setPos(foreground->mapToParent(
foreground->mapFromItem(background, (x, y))))
Does mapFromItem(item) account for any transformation applied to item? Or is the equivalency just an artifact of my overall situation?
If you define that foreground is the parent of background, Qt will translate background automatically if the position of foreground changes.
background->setParent(foreground);
background->setPos(20,20); // cooridinate system origin is pos() of foreground.
foreground->setPos(10,10); // background moves also
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.
I inherited from the QGraphicsObject and created a new class that has a pixmap and sets its transform origin point to:
setTransformOriginPoint(boundingRect().center());
But when I call setRotation() on the my class (which is added to a QGraphicsView using the scene), the rotation doesn't use the center as the rotation anchor. How can I set the center to be the anchor of the rotation ? Thanks !
More information: calling setRotation() outside of a sceneEvent function it works, but inside a sceneEvent, upon a pinch gesture, the origin point doesn't work.
Draw pixmap at QRect(0, 0, pixmap.width(), pixmap.height(). Use this rectangle for bounding rect also. Use setPos to move the item around the scene. Use setTransformOriginPoint(pixmap.width() / 2, pixmap.height() / 2) to set the origin point. These coordinates are in the item coordinates, so they should point at the pixmap's center regardless of the item's position.
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.