图像不适合图形视图框架

问题描述 投票:0回答:5

我正在开发一个程序,向用户显示他们选择的一些图片。我想将这张图片放入

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
px 时,图片尺寸约为
200
x
400
px。

可能出了什么问题?

c++ qt qt5 qgraphicsview qimage
5个回答
24
投票

我的问题的解决方案是 Dialog 的 showEvent() 。这意味着在显示表单之前你不能调用 fitInView() ,所以你必须为对话框创建 showEvent() ,图片将适合 QGraphics View 的框架。

以及您必须添加到对话框代码中的示例代码:

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

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
投票

你应该处理 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);
        }
}

1
投票

正如官方文档所说,将 Fitinview() 放在 override resizeEvent() 中;

” 缩放视图矩阵并滚动滚动条以确保场景矩形矩形适合视口内。矩形必须位于场景矩形内;否则,fitInView()不能保证整个矩形可见。

此函数保持视图的旋转、平移或剪切。视图根据aspectRatioMode 进行缩放。如果矩形不紧密贴合,它将在视图中居中。

通常从 resizeEvent() 的重新实现中调用 fitInView(),以确保整个场景或部分场景在视图大小调整时自动缩放以适应视口的新大小。但请注意,如果新转换切换了滚动条的自动状态,则从 resizeEvent() 内部调用 fitInView() 可能会导致不必要的调整大小递归。您可以将滚动条策略切换为始终打开或始终关闭以防止出现这种情况(请参阅horizontalScrollBarPolicy() 和verticalScrollBarPolicy())。 ”


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();
© www.soinside.com 2019 - 2024. All rights reserved.