图片不适合图形视图框架

16
我正在开发一个程序,它可以显示用户选择的一些图片。我希望将这些图片适应到QGraphicsView的框架中,但是图片显示出来比框架小。
所以这是我的代码:
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);

这是上面代码生成的一些示例和我想要得到的内容。

image showing produced and wanted looks

图片的尺寸大约是 40 x 60 像素,而框架的尺寸是 200 x 400 像素。
可能出了什么问题?

我知道这不是问题,但如果你把图片拉伸那么多,它会有点丑...此外,你想保持纵横比,但它们不同(图片是2/3和框架是1/2...)也许用一个200*300的框架? - Thomas Ayoub
除了QGraphicsView以外,有没有其他解决方案可以在对话框内显示图像? - user1257255
是的,您可以使用QLabel的setPixmap()方法。 - WoJo
如何将图像调整到QLabel的大小?我正在查看scaledContents,但它只会缩放图像而不保持比例... - user1257255
5个回答

24

解决方法是使用Dialog的showEvent()函数。这意味着在表单显示之前不能调用fitInView(),因此您必须为对话框创建showEvent()函数,然后图片将适合于QGraphics View的框架。

下面是示例代码,您需要将其添加到对话框的代码中:

void YourClass::showEvent(QShowEvent *) {
    ui->graphicsView->fitInView(scn->sceneRect(),Qt::KeepAspectRatio);
}

天啊!谢谢你!我已经查遍了 Qt 文档试图理解这个问题,但是它没有提到这个问题的参考资料! - mannysz
1
我在这之后遇到了一个问题,你是怎么解决白像素边框问题的?我有一个QDeclarativeView(它是一个GraphicsView),并尝试使用scene()->itemsBoundingBox()来fitInView,结果为1920x1080像素。尽管如此,它仍然保留了5像素的白色边框(因为场景背景颜色)。如果我设置setAlign(Qt :: Left | Qt :: Top),只会显示右下角的边距。任何提示吗? - mannysz
不同的解决方案:在“show()”之后运行设置视图的函数。 - user136036

3
你看不到想要的图像是因为QGraphicsView中的fitInView函数并不像你想象的那样工作。
该函数确保对象适合于视口,而不会与视图边框重叠,因此如果对象不在视图中,则调用fitInView将导致视图移动/缩放等以确保完全可见对象。此外,如果视口对于提供给fitInView的区域来说太小,就不会发生任何事情。
因此,要获得想要的效果,请将GraphicsView坐标的范围映射到GraphicsScene,并将图像的场景坐标设置为这些坐标。正如@VBB所说,如果您拉伸图像,则可能会更改其宽高比,因此您可以在QPixmap上使用scaledToWidth。
类似以下内容:-
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);

如果您的视口位置正确,且不想让图像看起来像素化,请使用分辨率高的图像。您可能会发现不需要调用fitInView函数。


1
根据官方文档的描述,在覆盖resizeEvent()时放置Fitinview()。
该函数缩放视图矩阵并滚动滚动条,以确保场景矩形rect适合于视口。 rect必须在场景矩形内;否则,fitInView()无法保证整个矩形可见。
此函数保持视图的旋转、平移或剪切。根据aspectRatioMode缩放视图。如果rect不紧密适合,则其将居中在视图中。
通常从resizeEvent()的重新实现中调用fitInView(),以确保整个场景或部分场景随着视图的调整自动缩放以适应视口的新大小。但是请注意,从resizeEvent()中调用fitInView()可能会导致不希望的调整递归,如果新转换切换滚动条的自动状态。您可以将滚动条策略切换为始终打开或始终关闭以防止这种情况(请参阅horizontalScrollBarPolicy()和verticalScrollBarPolicy())。

1
你应该处理resize事件,我想这就是它的本意所在。
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);
        }
}

0

我认为你应该对图片进行缩放。我这样做,效果很好:

QRect ref_Rect = QRect(x_pos, y_pos, Width, Length);
QGraphicsView* qGraph = new QGraphicsView(this);
qGraph->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
qGraph->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
qGraph->setGeometry(ref_Rect);

QGraphicsScene* scene = new QGraphicsScene(qGraph);
scene->setSceneRect(0, 0, ref_Rect.width(), ref_Rect.height());
qGraph->setScene(scene);

QImage *image = new QImage();
image->load("folder/name.png");
*image = image->scaled(ref_Rect.width(), ref_Rect.height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 
QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(*image));    

scene->addItem(item);
qGraph->show();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接