Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt5 C++ QGraphicsView: Images don't fit view frame

I'm working on program which shows user some picture that is selected by him. But there is a problem because I would like to fit this picture in QGraphicsView's frame and the picture is really smaller than the frame.

So here's my code:

image = new QImage(data.absoluteFilePath()); // variable data is defined when calling this method
scn = new QGraphicsScene(this); // object defined in header
ui->graphicsView->setScene(scn);
scn->addPixmap(QPixmap::fromImage(*image));
ui->graphicsView->fitInView(scn->itemsBoundingRect(),Qt::KeepAspectRatio);

I was trying a lot of solutions that I found on web, but no one didn't help me. The picture is in size around 40 x 60 px when the frame is 200 x 400 px. What could be wrong?

Here is some example of what is produced with code above and what I want to get out: enter image description here

like image 991
user1257255 Avatar asked Jun 10 '13 16:06

user1257255


4 Answers

Solution for my question is showEvent() for Dialog. This means that you can't call fitInView() before the form is showed, so you have to create showEvent() for dialog and the picture will be fitted into QGraphics View's frame.

And example code which you have to add into dialog's code:

void YourClass::showEvent(QShowEvent *) {
    ui->graphicsView->fitInView(scn->sceneRect(),Qt::KeepAspectRatio);
}
like image 116
user1257255 Avatar answered Nov 11 '22 15:11

user1257255


The reason you're not seeing your image as you want it is because the QGraphicsView function fitInView does not do what you think it does.

It ensures that the object fits inside the viewport, without any overlap of the borders of the view, so if your object was not in the view, calling fitInView will cause the view to move / scale etc to ensure that the object is completely visible. Also, if the viewport is too small for the area provided to fitInView, nothing will happen.

So, to get what you want, map the extents of the GraphicsView coordinates to the GraphicsScene and then set the image's scene coordinates to those. As @VBB said, if you stretch the image, it may change the aspect raio, so you can use scaledToWidth on the QPixmap.

Something like this: -

QRectF sceneRect = ui->graphicsView->sceneRect(); // the view's scene coords
QPixmap image = QPixmap::fromImage(*image);

// scale the image to the view and maintain aspect ratio
image = image.scaledToWidth(sceneRect.width());

QGraphicsPixmapItem* pPixmap = scn->addPixmap(QPixmap::fromImage(*image));

// overloaded function takes the object and we've already handled the aspect ratio
ui->graphicsView->fitInView(pPixmap);

You may find that you don't need the call to fitInView, if your viewport is in the right place and if you don't want it to look pixellated, use an image with a high resolution.

like image 31
TheDarkKnight Avatar answered Nov 11 '22 14:11

TheDarkKnight


You should handle resize event, I guess it's the way it's meant to be played:

bool YourDialog::eventFilter(QObject *obj, QEvent *event)
{
        if (event->type() == QEvent::Show){
            ui->conceptView->fitInView(conceptScene->sceneRect(), Qt::KeepAspectRatio);
        }

        if (event->type() == QEvent::Resize){
            ui->conceptView->fitInView(conceptScene->sceneRect(), Qt::KeepAspectRatio);
        }
}
like image 1
Dennis S Avatar answered Nov 11 '22 16:11

Dennis S


As official document says, put Fitinview() in override resizeEvent();

" Scales the view matrix and scrolls the scroll bars to ensure that the scene rectangle rect fits inside the viewport. rect must be inside the scene rect; otherwise, fitInView() cannot guarantee that the whole rect is visible.

This function keeps the view's rotation, translation, or shear. The view is scaled according to aspectRatioMode. rect will be centered in the view if it does not fit tightly.

It's common to call fitInView() from inside a reimplementation of resizeEvent(), to ensure that the whole scene, or parts of the scene, scales automatically to fit the new size of the viewport as the view is resized. Note though, that calling fitInView() from inside resizeEvent() can lead to unwanted resize recursion, if the new transformation toggles the automatic state of the scrollbars. You can toggle the scrollbar policies to always on or always off to prevent this (see horizontalScrollBarPolicy() and verticalScrollBarPolicy()). "

like image 1
Qiuren Avatar answered Nov 11 '22 14:11

Qiuren