I am making an application where I need to draw figures (i.e. rectangles) above a picture and resize the whole scene. I'm using QGraphicsView
and QGraphicsScene
. I can't figure out why but when I was using fitIntoView()
I was unable to draw figures on top of a picture (they probably were drawn behind the picture or outside the bounds).
Now I'm using QPixmap.scaled()
to make the image fit in the QGraphicsScene
. It works fine except when I need to display a big image and then zoom it in. Because I scaled the image to fit, it became smaller and when I call QGraphicsView.scale()
the image scales as small one and I can't find a way to "scale back" the image to original size.
In the zoom part of code I tried to replace pixmap with its not scaled copy but I can't scale it with the same proportions as my figures scaling. Any help would be appreciated!
Here I load the image and scale it
QPixmap pix;
pix = pixmap->scaled(wid, hei,Qt::KeepAspectRatio, Qt::SmoothTransformation);
scn = new QGraphicsScene(pw);
pw->setScene(scn);
p = new QGraphicsPixmapItem(pix);
p->setPixmap(pix);
scn->addItem(p);
I draw figures like this
rect = new QGraphicsRectItem(x,y,w,h);
rect->setPen(QPen(getColor(), 1, Qt::SolidLine, Qt::FlatCap));
scn->addItem(rect);
And here's how I zoom
pw->scale(scaleFactor_,scaleFactor_);
Update:
Now I have a QWidget
with kind of toolbar on the top, the rest of free space is filled with a custom QGraphicsView
. This is a derived class for grabbing mouse events, there's nothing more but overrides of event handlers. I'm adding PainterGraphicsView in my widget's constructor:
pw = new PainterGraphicsView();
ui->gridLayout_3->addWidget(pw);
I'm recreating the scene every time I load a new image into it:
scn = new QGraphicsScene(pw);
pw->setScene(scn);
QRect r = QRect(0,0, pw->width()-5, pw->height()-5);
scn->setSceneRect(r);
After I loaded an image I can draw figures on top of it, it looks like this:
And the scaled contents look like this:
As you can see, figures scaled together with a pixmap and this is exactly how I need it to work. The only thing I have to fix is the low quality of scaled pixmap. As I already said, I tried to replace pixmap with the original one in my ZoomIn method, but I can't do it saving figures' position.
void DrawerWidget::on_btZoom_clicked()
{
p->setPixmap(pix); //p is QGraphicsPixmapItem, pix is an original pixmap
p->setScale(0.5); //how can I scale the pixmap together with figures?? How to calculate the required scale?
pw->scale(scaleFactor_,scaleFactor_);
}
Update 2:
A short explanation on my drawing figures method: (though I personally don't think that this is the issue, I'm interested is there a way to scale QGraphicsPixmapItem using setScale() to fit in QGraphicsView size)
I'm getting start_
and end_
coordinates from mouse events arguments (QMouseEvent *e)
end_=pw->mapToScene(e->pos());
start_=pw->mapToScene(e->pos());
I add the figure on mousepress:
rect = new QGraphicsRectItem(start_.x(),start_.y(),1,1);
scn->addItem(rect);
And I redraw the figure on mouse move
rect->setRect(Graphics::GetFigure(start_.x(),start_.y(),end_.x(),end_.y()));
GetFigure is a method for calculating the figure's rect, here's main part of it:
static QRectF GetFigure(double startX, double startY, double finalX, double finalY)
{
QRectF shape;
shape.setX(startX);
shape.setY(startY);
shape.setWidth(qFabs(finalX - startX));
shape.setHeight(qFabs(finalY - startY));
return shape;
}
setScale(0.5)
and I expected QGraphicsPixmapItem to have twice less size, but I only got a square containing a part of original image inside. What can I miss here? – lenaQGraphicsView::scale
without causing your overlays to appear off-screen because you're not transforming your points between coordinate spaces correctly when placing your items based on mouse events. – cgmb