QGraphicsView滚动和图像缩放/裁剪。

时间:2023-01-12 21:22:22

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?

我想在我的QGraphicsView中有一个背景图像,它总是按比例缩放(如果有必要的话)到viewport的大小,没有滚动条,也不需要滚动键盘和鼠标。下面的例子是我在viewport中缩放和裁剪图像的方法,但是我使用的是被从aether中提取出来的裁剪的随机值。我想要一个合乎逻辑的解决方案?

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?

我想知道一种缩放和裁剪图像到QGraphicsView的大小的方法,即使我调整了QGraphicsView的大小,它也能工作。1。5和19是从哪里来的?

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

编辑;我也尝试使用setBackgroundBrush,但我得到了一个tiled背景,即使使用缩放/裁剪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.

编辑;到目前为止,我的解决方案是覆盖drawBackground()来获得我想要的结果,但这仍然不能帮助我学习如何将图像大小调整为qgraphicsview的viewport大小。如有任何进一步的答复,我们将不胜感激。

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()));

}

3 个解决方案

#1


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.

你想要的不仅仅是宽度和高度。对于调整大小,您希望将一个插槽连接到sceneRectChanged,以便您可以在场景更改大小时调整图像的大小。

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

或者,您可以使用重写的updatesceninstall来派生一个QGraphicsView,它会改变图像的大小,或者更好的是,只是覆盖drawBackground。

#2


0  

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

我找到了ui->graphicsView->viewport()->大小()来获取viewport的大小。不过,只有在小部件被绘制出来之后才可以工作。

#3


0  

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:

QGraphicsView::fitInView确实做到了这一点。根据文档,它通常被放置在一个resizeEvent中。使用sceneRects使整个场景适合于视图:

void CustomGraphicsView::resizeEvent(QResizeEvent *)
{
  this->fitInView(this->sceneRect());
}

#1


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.

你想要的不仅仅是宽度和高度。对于调整大小,您希望将一个插槽连接到sceneRectChanged,以便您可以在场景更改大小时调整图像的大小。

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

或者,您可以使用重写的updatesceninstall来派生一个QGraphicsView,它会改变图像的大小,或者更好的是,只是覆盖drawBackground。

#2


0  

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

我找到了ui->graphicsView->viewport()->大小()来获取viewport的大小。不过,只有在小部件被绘制出来之后才可以工作。

#3


0  

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:

QGraphicsView::fitInView确实做到了这一点。根据文档,它通常被放置在一个resizeEvent中。使用sceneRects使整个场景适合于视图:

void CustomGraphicsView::resizeEvent(QResizeEvent *)
{
  this->fitInView(this->sceneRect());
}