缩放视图矩形时防止缩放项目

发布于 2024-07-29 18:50:33 字数 204 浏览 8 评论 0原文

我正在使用 Qt 的 QGraphicsView 和 QGraphicsItem 子类。

当视图矩形发生更改(例如放大时)时,有没有办法不缩放视图中项目的图形表示形式。默认行为是我的项目相对于我的视图矩形进行缩放。

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

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 behavior is that my items scale in relation to my view rectangle.

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.

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

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

发布评论

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

评论(5

我早已燃尽 2024-08-05 18:50:33

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

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

手长情犹 2024-08-05 18:50:33

扩展 QGraphicsItem 类,重写 paint()

paint() 内,将变换的缩放因子重置为 1(即 m11m22),并保存 m11<重置之前的 /code> (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"); 
}

您可以尝试两者以查看差异。

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.

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
}

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.

携君以终年 2024-08-05 18:50:33

怎么样:

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

正如您所看到的,文本已放大,但矩形并未放大。 请注意,这不仅会阻止矩形的缩放,还会阻止其他变换。

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.

望笑 2024-08-05 18:50:33

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

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

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 measures, 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);
调妓 2024-08-05 18:50:33

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

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

I found that if I derive a new class and reimplement 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文