缩小比例的QPixmap:无法恢复原始大小

5
我正在制作一个应用程序,需要在图片上方绘制图形(如矩形),并调整整个场景的大小。我使用QGraphicsViewQGraphicsScene。但是当我使用fitIntoView()时,无法在图片上方绘制图形(它们可能被绘制在图片后面或超出了边界)。
现在,我使用QPixmap.scaled()将图像适应于QGraphicsScene。这很好用,除非我需要显示一个大图像然后对其进行缩放。因为我将图像缩小以适应,所以当我调用QGraphicsView.scale()时,图像会缩小,而我找不到“缩放回”原始大小的方法。
在代码的缩放部分,我尝试用未缩放的副本替换pixmap,但我无法按比例缩放它与我的图形缩放相同。
任何帮助都将不胜感激!

这里我加载图像并进行缩放

QPixmap pix;
pix = pixmap->scaled(wid, hei,Qt::KeepAspectRatio, Qt::SmoothTransformation);
scn = new QGraphicsScene(pw);
pw->setScene(scn);
p = new QGraphicsPixmapItem(pix);
p->setPixmap(pix);
scn->addItem(p);

我画出像这样的图形。
rect = new QGraphicsRectItem(x,y,w,h);
rect->setPen(QPen(getColor(), 1, Qt::SolidLine, Qt::FlatCap));
scn->addItem(rect);

这是我如何缩放的方法

pw->scale(scaleFactor_,scaleFactor_);

更新: 现在我有一个带有工具栏的 QWidget,其余的自由空间填充了一个自定义的 QGraphicsView。这是一个派生类,用于抓取鼠标事件,除了事件处理程序的覆盖外,没有其他内容。我在我的小部件构造函数中添加了 PainterGraphicsView :

pw = new PainterGraphicsView();
ui->gridLayout_3->addWidget(pw);

每次加载新图像时,我都会重新创建场景:

scn = new QGraphicsScene(pw);
pw->setScene(scn);
QRect r = QRect(0,0, pw->width()-5, pw->height()-5);
scn->setSceneRect(r);

在加载了一张图片后,我可以在其上绘制图形,效果如下:

enter image description here

缩放后的内容如下:

enter image description here

正如您所看到的,图像与像素图一起缩放,这正是我需要的工作方式。我唯一需要解决的问题是缩放后像素图的低质量。正如我已经提到的,我尝试在我的ZoomIn方法中使用原始像素图替换像素图,但我不能保存图形的位置。
void DrawerWidget::on_btZoom_clicked()
{
    p->setPixmap(pix); //p is QGraphicsPixmapItem, pix is an original pixmap
    p->setScale(0.5); //how can I scale the pixmap together with figures?? How to calculate the required scale?
    pw->scale(scaleFactor_,scaleFactor_);
}

enter image description here


更新2:

我的绘图方法简要解释:(尽管我个人认为这不是问题,但我想知道是否有一种方法使用setScale()来缩放QGraphicsPixmapItem以适应QGraphicsView的大小)

我从鼠标事件参数(QMouseEvent *e)中获取start_end_坐标。

 end_=pw->mapToScene(e->pos());
 start_=pw->mapToScene(e->pos());

我在鼠标按下时添加图形:
rect = new QGraphicsRectItem(start_.x(),start_.y(),1,1);
scn->addItem(rect);

我在鼠标移动时重新绘制图形

rect->setRect(Graphics::GetFigure(start_.x(),start_.y(),end_.x(),end_.y()));

GetFigure是一个用于计算图形矩形的方法,以下是其主要部分:

 static QRectF GetFigure(double startX, double startY, double finalX, double finalY)
    {
      QRectF shape;
      shape.setX(startX);
      shape.setY(startY);
      shape.setWidth(qFabs(finalX - startX));
      shape.setHeight(qFabs(finalY - startY));
      return shape;
   }

我不明白为什么你要缩放QPixmap。如果你想缩放图像并保持分辨率,可以缩放QGraphicsPixmapItem。 - Fabio
嗨@Fabio!谢谢您的回复!我缩放QPixmap是因为我可以将其缩放以适应宽度和高度,而使用QGraphicsPixmapItem,我必须以某种方式计算比例尺,但我不知道如何... :( - lena
如果图像小于QGraphicsScene的大小,那么就没问题,但我需要将大的图像缩小。据我所知,我需要使用从0到1的比例,但是我得到了奇怪的结果。我刚刚尝试了“setScale(0.5)”,并且我期望QGraphicsPixmapItem的大小减少一倍,但我只得到了一个包含原始图像部分的正方形。我错过了什么? - lena
抱歉,但这不是很清楚。我们需要更多的代码,也许还需要一些截图。 - Fabio
1
我怀疑你真正的问题是,当你基于鼠标事件放置你的物品时,你没有正确地在坐标空间之间转换你的点,因此你无法改变QGraphicsView::scale而不会导致你的覆盖层出现在屏幕外。 - cgmb
显示剩余10条评论
2个回答

5

缩放操作是破坏性的,一旦你缩小图像,你最终得到的数据比你开始的时候要少。

如果你想恢复原来的大小,可以保留一份原始的 pixmap 副本。

你可以从原始未经缩放的 pixmap 创建 QGraphicsPixmapItem,然后使用 QGraphicsPixmapItem::setScale(qreal) 更改级别图形项的大小,而不是级别 pixmap 数据的大小。这样缩放不应该是破坏性的,并且如果您将其扩大到原始大小,则不应该失去质量。

如果你想对多个项目进行缩放(并且不遇到不同的变换起点问题),你有几个选择:

  • 缩放整个视图-这将缩放所有内容
  • 将项目添加为父项的子项,然后缩放父项也会缩放其子项

项目的转换从父级到子级逐渐累积

  • 使用 createItemGroup() 将项目添加到组中:

项目都被重新设置为组的子项,并将它们的位置和 变换映射到组


是的,在我在SO上发布之前,我尝试过这个解决方案,但我不知道如何与我在其上绘制的图形一起缩放QGraphicsPixmapItem。请参见我的编辑后的问题。 - lena
使用您的方法,我在我的Zoom方法中用原始图像的副本替换了缩小的QPixmap,但是滚动条没有像使用QGraphicsView.scale()时那样出现,因此我无法浏览图像。我错过了什么? - lena

1
我认为你的问题是将场景矩形设置为QGraphicsView矩形。这是不正确的,因为窗口参考系统与场景参考系统不同。
你不需要设置场景矩形,因为当你添加一些项时,场景矩形会自动增长。如果你想将场景矩形限制为像素图矩形,则可以将场景矩形设置为QPixampItem边界矩形。
你不需要缩放原始像素图。要缩放视图,只需调用QGrapicsView::scale。你还可以调用QGrapicsView::fitInView来适应视图中的图像。
如果你需要添加一些由用户绘制的矩形(即在窗口坐标中),你可以使用QGraphiscView::mapToScene将窗口坐标映射到场景坐标。
我建议阅读关于参考系统的文档:The Graphics View Coordinate System

我更喜欢场景与QGraphicsView相同的大小和位置,即填充窗口的所有空闲空间,这可能吗?当我尝试使用fitInView方法并尝试绘制图形时,它们没有被绘制。这也可能是由于坐标不一致引起的吗? - lena
我复制了有关绘制图形的注释:void DrawerWidget::onMousePress(QMouseEvent *e) { start_=pw->mapToScene(e->pos()); end_=pw->mapToScene(e->pos()); } 我从我的子类化的 QGraphicsView 中捕获信号,并使用 start_end_ 点在鼠标移动时绘制图形。 - lena
使用 mapToScene 是正确的,但是不清楚如何使用 start_ 和 end_ 。请发布更多代码。同时,请确保为项目设置正确的 zValue。 - Fabio
还要确保将美工笔设置为矩形项。 - Fabio
我当然使用笔,只是我在帖子中没有包括这个。 - lena
显示剩余3条评论

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