QGraphicsView和QGraphicsItem:当缩放视图矩形时不要缩放项

11
我正在使用Qt的和子类。是否有一种方法可以在更改视图矩形时,例如缩放视图时,不对项目的图形表示进行缩放。默认行为是,我的项目会根据视图矩形进行缩放。
我想要可视化2D点,应该由一个细长的矩形来表示,在查看时不应进行缩放。请参考典型的3D建模软件,其中顶点点始终以相同的大小显示。
谢谢!

1
如果您正在使用自定义绘画例程,请查看http://doc.trolltech.com/4.5/qpen.html#setCosmetic - mpen
5个回答

12
QGraphicItem的标志QGraphicsItem :: ItemIgnoresTransformations设置为true对您无效吗?

5
确保物品大小正确,但至少在我的情况下,在变换后位置会出现偏差。举例来说,当我在我的应用程序中绘制一个多边形,并在未缩放(1:1)视图中添加子矩形项时,我得到以下结果:http://grafit.mchtr.pw.edu.pl/~szczedar/nozoom.png。缩放并设置标志后,它看起来像这样:http://grafit.mchtr.pw.edu.pl/~szczedar/zoomout.png - neuviemeporte
1
文档中说设置了标志的项目会停留在父级,但我将矩形对象创建为多边形的父级,却没有起作用。尝试使用底层的像素图项目作为父级,也没有改变。 - neuviemeporte

10
我遇到了同样的问题,花费了一些时间才解决了它。以下是我的解决方法。
继承QGraphicsItem类,并重写paint()函数。 在paint()函数中,将变换的缩放因子重置为1(即m11和m22),并在重置之前保存m11(x缩放因子)和m22(y缩放因子)。 然后,像平常一样绘制,但是将你的x乘以m11,将y乘以m22。这样可以避免使用默认的变换进行绘制,而是根据场景的变换显式地计算位置。
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
    QTransform t = painter->transform();
    qreal m11 = t.m11(), m22 = t.m22();
    painter->save(); // save painter state
    painter->setTransform(QTransform(1, t.m12(), t.m13(),
                                     t.m21(), 1, t.m23(), t.m31(),
                                     t.m32(), t.m33()));
    int x = 0, y = 0; // item's coordinates
    painter->drawText(x*m11, y*m22, "Text"); // the text itself will not be scaled, but when the scene is transformed, this text will still anchor correctly
    painter->restore(); // restore painter state
}

以下代码块使用默认转换进行绘制。
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
    int x = 0, y = 0;
    painter->drawText(x, y, "Text"); 
}

你可以尝试两种方式来查看区别,希望这能帮助到你。


4
回答不错,但我认为QTransform实例化行中的m11应该是1而不是其他值。 - Canol Gökel
我在答案中修复了这个问题,谢谢@CanolGökel。 - Kai

2
这样怎么样:
#include <QtGui/QApplication>
#include <QtGui/QGraphicsScene>
#include <QtGui/QGraphicsView>
#include <QtGui/QGraphicsRectItem>

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    QGraphicsScene scene;
    scene.addText("Hello, world!");
    QRect rect(50, 50, 100, 100);
    QGraphicsRectItem* recti = scene.addRect(rect);
    QGraphicsView view(&scene);

    // Set scale for the view
    view.scale(10.0, 5.0);

    // Set the inverse transformation for the item
    recti->setTransform(view.transform().inverted());

    view.show();
    return app.exec();
}

正如您所看到的,文本被放大了,但矩形没有。请注意,这不仅防止了矩形的缩放,还防止了其他变换。


2
以下解决方案对我非常有效:
void MyDerivedQGraphicsItem::paint(QPainter *painter, const StyleOptionGraphicsItem *option, QWidget *widget)
{
    double scaleValue = scale()/painter->transform().m11();
    painter->save();
    painter->scale(scaleValue, scaleValue);
    painter->drawText(...);
    painter->restore();
    ...
}

我们还可以将scaleValue乘以其他我们想要保持其在save/restore环境之外大小恒定的度量单位。
    QPointF ref(500, 500);
    QPointF vector = scaleValue * QPointF(100, 100);
    painter->drawLine(ref+vector, ref-vector);

1
我发现如果我派生一个新类并重新实现绘制函数,我可以做到。
void MyDerivedQGraphicsItem::paint(QPainter *painter, 
                                   const QStyleOptionGraphicsItem *option, 
                                   QWidget *widget)
{
  double scaleValue = scale();
  double scaleX = painter->transform().m11();
  setScale(scaleValue / scaleX);
  QGraphicsSvgItem::paint(painter,option,widget);
}

这是我到目前为止发现的最好的方法,但我仍在不断尝试探索。


1
嗯,这对我没用(在我的情况下,我正在子类化QGraphicsEllipseItem)。当我放大视图时,项目仍然变大。除了上面的内容,你还做了什么吗? - estan
抱歉,实际上它确实起作用了。但如果你找到其他方法,我会很感兴趣的。因为当我快速缩放视图(使用滚轮)时,我会注意到一些闪烁:/ - estan
抱歉,不行,我仍然遇到了一些问题,但它已被放弃了。 - enriched
setScale 调度了项目的重新绘制,所以我猜你的代码可能会导致无限循环。并且 painter->transform().m11() 只在没有对项目应用旋转时才给出比例尺。 - user1482030

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