´QGraphicsView QGraphicsItem:不规模项目当缩放视图矩形

时间:2022-06-14 21:22:07

I am using Qt´s QGraphicsView- and QGraphicsItem-subclasses. is there a way to not scale the graphical representation of the item in the view when the view rectangle is changed, e.g. when zooming in. The default behaviour is that my items scale in relation to my view rectangle.

我使用Qt´s QGraphicsView QGraphicsItem-subclasses。是否有一种方法可以在视图矩形发生变化时(例如放大时)不缩放视图中项目的图形表示?默认行为是,我的项与我的视图矩形相关。

I would like to visualize 2d points which should be represented by a thin rectangle which should not scale when zooming in the view. See a typical 3d modelling software for reference where vertex points are always shown at the same size.

我想把二维点形象化,它应该用一个不应该缩放的矩形来表示。请参阅典型的3d建模软件,以获得顶点总是以相同的大小显示。

Thanks!

谢谢!

5 个解决方案

#1


9  

Set the item's flag QGraphicsItem::ItemIgnoresTransformations to true does not work for you?

设置项目的标志QGraphicsItem:: itemignorestransformation to true不适合你吗?

#2


4  

I got into the same problem, and it took me a while to figure it out. This is how I solved it.

我也遇到了同样的问题,我花了一段时间才弄明白。我就是这样解出来的。

Extend a QGraphicsItem class, override paint(). Inside the paint(), reset the transformation's scaling factor to 1(which are m11 and m22), and save the m11(x scaling factor) and m22(y scaling factor) before the reset. Then, draw like you would normally do but multiply your x with m11 and y with m22. This avoids drawing with the default transformation, but explicitly calculates the positions according to the scene's transformation.

扩展一个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(m11, 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
}

The following code block is drawing with default transformation

下面的代码块使用默认转换绘制

void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
    int x = 0, y = 0;
    painter->drawText(x, y, "Text"); 
}

You can try both to see the difference. Hope this helps.

你可以试着看两者的区别。希望这个有帮助。

#3


2  

How about this:

这个怎么样:

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

As you can see the text is scaled up but the rectangle is not. Note that this does not only prevent the scaling for the rectangle but and other transformation.

你可以看到文本被放大了,但矩形不是。注意,这不仅阻止了对矩形的缩放,还阻止了其他的变换。

#4


1  

I found that if I derive a new class and reimpliment the paint function I can do

我发现,如果我推出一个新的类,并重新设计绘制函数,我可以做

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

This is the best way of doing it that I have found so far, but I am still tinkering around.

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

#5


1  

The following solution worked perfectly for me:

下面的解决方案对我来说非常有效:

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();
    ...
}

We can also multiply the scaleValue by other mesures we want to keep its size constant outside the save/restore environment.

我们还可以将标量乘以我们希望在保存/恢复环境之外保持其大小不变的其他中间层。

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

#1


9  

Set the item's flag QGraphicsItem::ItemIgnoresTransformations to true does not work for you?

设置项目的标志QGraphicsItem:: itemignorestransformation to true不适合你吗?

#2


4  

I got into the same problem, and it took me a while to figure it out. This is how I solved it.

我也遇到了同样的问题,我花了一段时间才弄明白。我就是这样解出来的。

Extend a QGraphicsItem class, override paint(). Inside the paint(), reset the transformation's scaling factor to 1(which are m11 and m22), and save the m11(x scaling factor) and m22(y scaling factor) before the reset. Then, draw like you would normally do but multiply your x with m11 and y with m22. This avoids drawing with the default transformation, but explicitly calculates the positions according to the scene's transformation.

扩展一个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(m11, 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
}

The following code block is drawing with default transformation

下面的代码块使用默认转换绘制

void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
    int x = 0, y = 0;
    painter->drawText(x, y, "Text"); 
}

You can try both to see the difference. Hope this helps.

你可以试着看两者的区别。希望这个有帮助。

#3


2  

How about this:

这个怎么样:

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

As you can see the text is scaled up but the rectangle is not. Note that this does not only prevent the scaling for the rectangle but and other transformation.

你可以看到文本被放大了,但矩形不是。注意,这不仅阻止了对矩形的缩放,还阻止了其他的变换。

#4


1  

I found that if I derive a new class and reimpliment the paint function I can do

我发现,如果我推出一个新的类,并重新设计绘制函数,我可以做

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

This is the best way of doing it that I have found so far, but I am still tinkering around.

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

#5


1  

The following solution worked perfectly for me:

下面的解决方案对我来说非常有效:

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();
    ...
}

We can also multiply the scaleValue by other mesures we want to keep its size constant outside the save/restore environment.

我们还可以将标量乘以我们希望在保存/恢复环境之外保持其大小不变的其他中间层。

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