QGraphicsView и QGraphicsItem: не масштабировать элемент при масштабировании прямоугольника представления - PullRequest
9 голосов
/ 03 августа 2009

Я использую Qt´s QGraphicsView - и QGraphicsItem -подклассы. есть ли способ не масштабировать графическое представление элемента в виде, когда прямоугольник вида изменяется, например, при увеличении. Поведение по умолчанию состоит в том, что мои элементы масштабируются относительно моего прямоугольника вида.

Я хотел бы визуализировать 2d точки, которые должны быть представлены тонким прямоугольником, который не должен масштабироваться при масштабировании вида. Обратитесь к типичному программному обеспечению для 3D-моделирования, где точки вершин всегда отображаются одинакового размера.

Спасибо!

Ответы [ 5 ]

10 голосов
/ 19 августа 2009

Установить флаг QGraphicItem QGraphicsItem::ItemIgnoresTransformations на true, у вас не работает?

4 голосов
/ 22 июля 2014

Я попал в ту же проблему, и мне потребовалось время, чтобы понять это. Вот как я это решил.

Расширить класс 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
}

Следующий блок кода рисует с преобразованием по умолчанию

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

Вы можете попробовать оба варианта, чтобы увидеть разницу. Надеюсь это поможет.

2 голосов
/ 04 августа 2009

Как насчет этого:

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

Как видите, текст масштабируется, а прямоугольник - нет. Обратите внимание, что это предотвращает не только масштабирование прямоугольника, но и другие преобразования.

1 голос
/ 14 ноября 2016

Следующее решение отлично сработало для меня:

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);
1 голос
/ 28 марта 2013

Я обнаружил, что если я получу новый класс и переопределю функцию рисования, я смогу выполнить

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

Это лучший способ сделать это, который я нашел до сих пор, но я все еще возился.

...