【问题标题】:Zoom in scaled down QPixmap: can't restore original size放大缩小的 QPixmap:无法恢复原始大小
【发布时间】:2016-06-09 16:40:14
【问题描述】:

我正在制作一个应用程序,我需要在图片上方绘制图形(即矩形)并调整整个场景的大小。我正在使用QGraphicsView 和QGraphicsScene。我不知道为什么,但是当我使用 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);

加载图像后,我可以在其上绘制图形,它看起来像这样:

缩放后的内容是这样的:

如您所见,数字与像素图一起缩放,这正是我需要它的工作方式。我唯一需要解决的是缩放像素图的低质量。正如我已经说过的,我尝试在 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_);
}


更新 2:

关于我的绘图方法的简短解释:(虽然我个人认为这不是问题,但我感兴趣的是有没有一种方法可以使用 setScale() 缩放 QGraphicsPixmapItem 以适应 QGraphicsView 大小)

我从鼠标事件参数 (QMouseEvent *e) 获取 start_ 和 end_ 坐标

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

我在 mousepress 上添加图形:

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。
  • 嗨@法比奥!感谢您的答复!我缩放 QPixmap 因为我可以缩放它以适应宽度和高度,并且使用 QGraphicsPixmapItem 我必须以某种我不知道如何计算的缩放率...... :(
  • 图片小于 QGraphicsScene 大小是可以的,但我需要将大图像变小。据我了解,我需要使用从 0 到 1 的比例,但结果很奇怪。我刚刚尝试了setScale(0.5),我希望 QGraphicsPixmapItem 的大小要小两倍,但我只有一个正方形,里面包含原始图像的一部分。我可以在这里错过什么?
  • 抱歉,不是很清楚。我们需要更多代码,也许还需要一些截图。
  • 我怀疑您的真正问题是您无法更改 QGraphicsView::scale 而不会导致您的叠加层出现在屏幕外,因为您在放置您的坐标空间时没有正确转换坐标空间之间的点基于鼠标事件的项目。

标签: qt qgraphicsview qgraphicsscene qpixmap


【解决方案1】:

缩放操作具有破坏性,一旦缩小,最终得到的数据就会比开始时少。

如果您希望能够恢复原始大小,请保留原始像素图的副本。

您可以从原始的未缩放像素图创建QGraphicsPixmapItem,然后使用QGraphicsPixmapItem::setScale(qreal) 更改关卡图形项的大小,而不是关卡像素图数据。这种方式缩放不应该是破坏性的,如果你将它放大到原始大小,你不应该失去质量。

如果您想缩放多个项目(并且不会遇到不同的转换来源问题),您有几个选择:

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

项转换从父级到子级累积

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

所有项目都重新分配给该组,并且它们的位置和 转换映射到组

【讨论】:

  • 是的,我在发布 SO 之前尝试了这个解决方案,但我不知道如何缩放 QGraphicsPixmapItem 以及我在其上绘制的数字。请查看我编辑的问题。
  • 使用您的方法,在我的 Zoom 方法中,我将缩小的 QPixmap 替换为原始副本的副本,但滚动条没有像 QGraphicsView.scale() 那样出现,所以我无法导航通过图像。我在这里错过了什么?
【解决方案2】:

我认为您的问题是您将场景矩形设置为QGraphicsView 矩形。这是不正确的,因为窗口参考系统与场景参考系统不同。 您不需要设置场景矩形,因为当您添加一些项目时,场景矩形会自动增长。如果要将场景矩形限制为像素图矩形,可以将场景矩形设置为QPixampItem边界矩形。

您不需要缩放原始像素图。要缩放您的视图,只需致电QGrapicsView::scale。您也可以调用QGrapicsView::fitInView 以使图像适合视图。

如果您需要添加一些用户绘制的矩形(即在窗口坐标中),您可以使用QGraphiscView::mapToScene将窗口坐标映射到场景坐标

我建议阅读有关参考系统的文档:The Graphics View Coordinate System

【讨论】:

  • 我希望场景的大小和位置与QGraphicsView 相同,即填充窗口的所有可用空间,这可能吗?当我尝试fitInView 方法然后尝试绘制他们没有被绘制的数字时。会不会也是这个坐标不一致造成的?
  • 我复制了我关于绘图的评论:` void DrawerWidget::onMousePress(QMouseEvent *e) { start_=pw->mapToScene(e->pos()); end_=pw->mapToScene(e->pos()); } ` 我从我的子类QGraphicsView 捕获信号并使用start_ 和end_ 点在鼠标移动时绘制图形
  • 使用 mapToScene 是正确的,但不清楚如何使用 start_ end end_ 。请发布更多代码。还要确保为项目设置正确的 zValue
  • 这似乎是正确的。您还在 mouseMoveEvent 中使用 mapToScene 吗?您是否为项目设置了 zValue?您可以将 QGraphicsPixmaItem zValue 设置为 -1(默认值为 0,因此您可以确定矩形绘制在图片上方而不是下方)。您还可以使用将 2 个角作为参数的 QRectF 构造函数,而不是创建特定函数来创建矩形 (QRectF(start_, end_))
  • 另外,请务必在矩形项目上设置化妆笔
猜你喜欢
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
  • 2017-12-14
  • 2021-12-11
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
相关资源
最近更新 更多