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

Posted

技术标签:

【中文标题】QGraphicsView 和 QGraphicsItem:缩放视图矩形时不要缩放项目【英文标题】:QGraphicsView and QGraphicsItem: don´t scale item when scaling the view rect 【发布时间】:2010-11-16 09:54:29 【问题描述】:

我正在使用 Qt 的 QGraphicsView - 和 QGraphicsItem-子类。 有没有办法在视图矩形更改时不缩放视图中项目的图形表示,例如放大时。默认行为是我的项目相对于我的视图矩形进行缩放。

我想可视化 2d 点,这些点应该由一个细长的矩形表示,在放大视图时不应缩放。请参阅典型的 3D 建模软件以供参考,其中顶点始终以相同大小显示。

谢谢!

【问题讨论】:

如果您使用的是自定义绘制程序,也可以在 doc.trolltech.com/4.5/qpen.html#setCosmetic 上达到峰值 【参考方案1】:

QGraphicItem 的标志QGraphicsItem::ItemIgnoresTransformations 设置为true 对您不起作用?

【讨论】:

这确实确保了项目的大小是正确的,但至少在我的情况下,转换后位置是关闭的。例如,当我在我的应用程序中绘制一个多边形,并在未缩放 (1:1) 视图中添加子矩形项时,我得到以下结果:grafit.mchtr.pw.edu.pl/~szczedar/nozoom.png。缩放并设置标志后,它看起来像这样:grafit.mchtr.pw.edu.pl/~szczedar/zoomout.png 文档说带有标志集的项目保持锚定到父级,但我创建了以多边形为父级的矩形对象,但它不起作用。也尝试将底层像素图项作为父项,没有变化。【参考方案2】:

我遇到了同样的问题,我花了一段时间才弄清楚。我就是这样解决的。

扩展一个 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"); 

您可以尝试两者来查看差异。希望这会有所帮助。

【讨论】:

很好的答案,但我认为 QTransform 实例化行上的 m11 应该改为 1。 我在答案中解决了这个问题,谢谢@CanolGökel【参考方案3】:

这个怎么样:

#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();

如您所见,文本已按比例放大,但矩形未按比例放大。请注意,这不仅会阻止矩形的缩放,还会阻止其他转换。

【讨论】:

【参考方案4】:

以下解决方案非常适合我:

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 乘以我们希望在保存/恢复环境之外保持其大小不变的其他度量。

    QPointF ref(500, 500);
    QPointF vector = scaleValue * QPointF(100, 100);
    painter->drawLine(ref+vector, ref-vector);

【讨论】:

【参考方案5】:

我发现如果我派生一个新类并重新实现我可以做的绘制函数

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);

这是迄今为止我发现的最好的方法,但我仍在修补。

【讨论】:

嗯。这对我不起作用(在我的情况下,我是 QGraphicsEllipseItem 的子类)。当我放大视图时,项目仍然变大。除了上述之外,您还做了什么? 呸,抱歉,它确实有效。但如果你找到其他方法,我会很感兴趣?因为当我快速缩放视图(使用滚轮)时,我会注意到一些闪烁:/ 对不起,不,我仍然遇到一些问题,但它被放弃了。 setScale 安排重绘项目,所以我猜您的代码可能会导致无限循环。当且仅当没有对项目应用旋转时,painter->transform().m11() 才会给出比例。

以上是关于QGraphicsView 和 QGraphicsItem:缩放视图矩形时不要缩放项目的主要内容,如果未能解决你的问题,请参考以下文章

使用 QGraphicsView 时小部件背景不透明,但使用 QGridLayout 时透明

Qt QGraphics在中心查看一张背景图片

qt获取滚动视图位置

结合 Qgraphics 和 sqlalchemy 时出现元类错误

最初在 QGraphics 中移动滚动条

Qt - 使用 QTransform(或类似的),将内部 QRect 缩放到 QGraphics/从 QGraphics