QGraphicsView scrolling and image scaling/cropping
Asked Answered
R

3

6

I would like to have a background image in my QGraphicsView that is always scaled (and cropped if necessary) to the size of the viewport, without scrollbars and without scrolling with the keyboard and mouse. The example below is what I am doing to scale and crop an image in the viewport, but I am using random values for the cropping that are pulled out of the aether. I would like a logical solution?

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    scene = new QGraphicsScene(this);

    ui->graphicsView->resize(800, 427); 
    // MainWindow is 800x480, GraphicsView is 800x427. I want an image that
    // is the size of the graphicsView.

    ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    // the graphicsView still scrolls if the image is too large, but 
    // displays no scrollbars. I would like it not to scroll (I want to 
    // add a scrolling widget into the QGraphicsScene later, on top of
    // the background image.)


    QPixmap *backgroundPixmap = new QPixmap(":/Valentino_Bar_Prague.jpg");
    QPixmap sized = backgroundPixmap->scaled(
            QSize(ui->graphicsView->width(), 
                  ui->graphicsView->height()),
            Qt::KeepAspectRatioByExpanding); // This scales the image too tall

    QImage sizedImage = QImage(sized.toImage());
    QImage sizedCroppedImage = QImage(sizedImage.copy(0,0,
       (ui->graphicsView->width() - 1.5),
       (ui->graphicsView->height() + 19))); 
    // so I try to crop using copy(), and I have to use these values
    // and I am unsure why.

    QGraphicsPixmapItem *sizedBackground = scene->addPixmap(
        QPixmap::fromImage(sizedCroppedImage));
    sizedBackground->setZValue(1);
    ui->graphicsView->setScene(this->scene);
}

I would like to know a way to scale and crop an image to the size of the QGraphicsView that will work even when I resize the QGraphicsView. Where are the 1.5 and 19 coming from?

EDIT; I have also attempted to use setBackgroundBrush, but I get a tiled background, even when using the scaled/cropped QImage/QPixmap.

EDIT; My solution thus far has been to override drawBackground() to get the result I wanted, but this still doesn't help me learn how to size an image to the viewport size of a qgraphicsview. Any further answers would be greatly appreciated.

void CustomGraphicsView::drawBackground( QPainter * painter, const QRectF & rect )
{

    qDebug() << "background rect: " << rect << endl;

    QPixmap *backgroundPixmap = new QPixmap(":/Valentino_Bar_Prague.jpg");
    QPixmap sized = backgroundPixmap->scaled(QSize(rect.width(), rect.height()), Qt::KeepAspectRatioByExpanding);

    painter->drawPixmap(rect, sized, QRect(0.0, 0.0, sized.width(), sized.height()));

}
Rhododendron answered 22/3, 2010 at 2:47 Comment(0)
C
1

You want sceneRect not just width and height. For the scaling on resize you want to connect a slot to sceneRectChanged so you can resize the image whenever the scene changes size.

Or you can derive a QGraphicsView with an overridden updateSceneRect that changes the image size, or better yet, just override drawBackground.

Costumier answered 22/3, 2010 at 16:50 Comment(1)
From the documentation: "The scene rect defines the extent of the scene, and in the view's case, this means the area of the scene that you can navigate using the scroll bars." sceneRect is not what I want, that gives me the size of the scene, regardless of what the viewport dimensions are. I want the viewport dimensions. I want to size an image to those dimensions. This seems simple; grab the width/height of the qgraphicsview and the job should be done. But the width and height are not correct when I scale an image to that size: what is the missing part here? I will try drawBackground.Rhododendron
K
1

The QGraphicsView::fitInView does exactly this. According to the documentation, it is commonly put in a resizeEvent. Using sceneRects makes the entire scene fit into the view:

void CustomGraphicsView::resizeEvent(QResizeEvent *)
{
  this->fitInView(this->sceneRect());
}
Kendre answered 5/11, 2016 at 10:10 Comment(0)
M
0

I found ui->graphicsView->viewport()->size() to get the viewport's size. Only works after the widget's been drawn though.

Medardas answered 30/7, 2010 at 8:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.