缩放 QGraphicsItem 以适合 QGraphicsView

发布于 2024-11-01 07:40:29 字数 1476 浏览 0 评论 0原文

我正在尝试创建一个QGraphicsView,它允许某人缩放当前QGraphicsItem以适应QGraphicsView窗口的大小。

我已经重写了 QGraphicsItem 来创建自定义版本,并且我实现了一些方法,以便它知道它已缩放了多少(始终与原始版本成正比,因此只有一个缩放因子 - 相同)对于宽度和高度)。

因此,在 scaleFactor 设置器中,我有以下内容:

void ImagePixmapItem::setScaleFactor(float sf){
    scaleFactor = sf;
    this->boundingRect().setWidth(this->boundingRect().width()*scaleFactor);
    this->boundingRect().setHeight(this->boundingRect().height()*scaleFactor);

}

在我的主窗体中,我在按钮中具有以下内容:

   QRect portRect = ui->graphicsView->viewport()->rect();
    double scaleFactorX;
   if(portRect.width() <= (item->boundingRect().size().width()))
       scaleFactorX =portRect.width() /(item->boundingRect().size().width());
   else
       scaleFactorX = (item->boundingRect().size().width())/portRect.width();

    qDebug("Scalefactor: %4.3f \n", scaleFactorX);
    qDebug("item width: %4.3f \n", item->boundingRect().size().width());
    qDebug("item height: %4.3f \n", item->boundingRect().size().height());
    item->setScaleFactor(scaleFactorX);
    item->scale(scaleFactorX,scaleFactorX);

其中 item 是其中之一 ImagePixmapItems.

第一次效果很好 - 我的图像比视口大,并且它可以很好地缩小以适应窗口(至少在宽度方面)。但是,如果我再次点击按钮,则 scaleFactorXitem 宽度和高度会返回相同的值。

变换后的图像可以更改其 boundingRect 吗?如果没有,我该怎么办?

I am trying to create a QGraphicsView that will allow someone to scale the current QGraphicsItem to fit the size of the QGraphicsView window.

I have overridden QGraphicsItem to create a custom version, and I implemented some methods so it knows how much it has been scaled (which is always proportional to the original, so there is only one scale factor - the same for width and height).

So in the scaleFactor setter I have the following:

void ImagePixmapItem::setScaleFactor(float sf){
    scaleFactor = sf;
    this->boundingRect().setWidth(this->boundingRect().width()*scaleFactor);
    this->boundingRect().setHeight(this->boundingRect().height()*scaleFactor);

}

And in my main form, I have the following in a button:

   QRect portRect = ui->graphicsView->viewport()->rect();
    double scaleFactorX;
   if(portRect.width() <= (item->boundingRect().size().width()))
       scaleFactorX =portRect.width() /(item->boundingRect().size().width());
   else
       scaleFactorX = (item->boundingRect().size().width())/portRect.width();

    qDebug("Scalefactor: %4.3f \n", scaleFactorX);
    qDebug("item width: %4.3f \n", item->boundingRect().size().width());
    qDebug("item height: %4.3f \n", item->boundingRect().size().height());
    item->setScaleFactor(scaleFactorX);
    item->scale(scaleFactorX,scaleFactorX);

Where item is one of those ImagePixmapItems.

This works good the first time time - my image is larger than the viewport, and it scales down nicely to fit the window (at least width wise). However, if I hit the button again, the same value for scaleFactorX and item width and height come back.

Can you change the boundingRect of an image after it has been transformed? If not, what should I do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

墨落画卷 2024-11-08 07:40:29

首先, QGraphicsItem::boundingRect() 返回矩形的副本。更改它对实际项目没有影响。要更改项目的几何形状,您需要覆盖该函数并返回不同的矩形。并在实际更改时调用 prepareGeometryChange()它。

现在,如果您想要的只是使项目适合 QGraphicsView 的视口,请使用 QGraphicsView::fitInView()

更改项目的变换与更改从场景到视图的变换有很大不同。前者改变了项目在场景中相对于其他项目的放置方式。后者保持关系并且仅影响场景如何“反射”到视图上。

如果场景中只有一个项目,那并没有多大区别。请记住,当您处理更复杂的场景时,项目转换涉及您的世界的数学模型,而不是如何查看它。

编辑:

我刚刚重读了您的代码。事实证明你计算的比例因子是错误的。这是一个基本的、未经测试的代码:

QRect itemSize = graphicsView->mapFromScene(item->sceneBoundingRect()).boundingRect().size();
QRect scaledSize =itemSize.scale(graphicsView->viewport().size(), Qt::KeepAspectRatio);
double ratio = qMin((double)scaledSize.width()/itemSize().width(), (double)scaledSize.height()/itemSize().height());
item->setTransform(QTransform::fromScale(ratio,ratio), true);

重点是使用 sceneBoundingRect 而不是 boundingRect 因为 boundingRect 是项目本地边界,它始终是无论项目变换如何,都相同。 sceneBoundingRect 是应用所有变换后的边界。

First of all, QGraphicsItem::boundingRect() returns a copy of the rect. Changing it has no effect on the actual item. To change an item's geometry, you need to override that function and return a different rect. And call prepareGeometryChange() when you actually change it.

Now, if all you want is to fit the item in QGraphicsView's viewport, use QGraphicsView::fitInView().

Changing the transformation of an item is very different from changing the transformation from the scene to the view. The former changes how the item is placed in the scene in relation to other items. The later keeps the relation and only affect how the scene is "reflected" onto the view.

It doesn't make much difference if you have a single item in the scene. Just keep in mind when you are dealing more complex scene that item transformation deals with the mathematical model of your world, not how to view it.

Edit:

I just reread your code. It turns out you are calculating the scale factor wrong. Here's a basic, non-tested code:

QRect itemSize = graphicsView->mapFromScene(item->sceneBoundingRect()).boundingRect().size();
QRect scaledSize =itemSize.scale(graphicsView->viewport().size(), Qt::KeepAspectRatio);
double ratio = qMin((double)scaledSize.width()/itemSize().width(), (double)scaledSize.height()/itemSize().height());
item->setTransform(QTransform::fromScale(ratio,ratio), true);

The point is to use sceneBoundingRect instead of boundingRect since boundingRect is the item local bounds which is always the same regardless of item transform. And sceneBoundingRect is the bounds after all transformations are applied.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文