我在QGraphicsScene中有一些QGraphicsItems,它们在缩放时应保持相同的大小和位置。我已经尝试过QGraphicsItem :: ItemIgnoresTransformations,但事实证明这些项目的位置错误。以下是示例代码:
我已将QGraphicsView子类化为:
class Graphics : public QGraphicsView
{
public:
Graphics();
QGraphicsScene *scene;
QGraphicsRectItem *rect;
QGraphicsRectItem *rect2;
protected:
void wheelEvent(QWheelEvent *event);
};
在其构造函数中:
Graphics::Graphics()
{
scene = new QGraphicsScene;
rect = new QGraphicsRectItem(100,100,50,50);
rect2 = new QGraphicsRectItem(-100,-100,50,50);
scene->addLine(0,200,200,0);
rect->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
scene->addItem(rect);
scene->addItem(rect2);
setScene(scene);
scene->addRect(scene->itemsBoundingRect());
}
wheelEvent虚函数:
void Graphics::wheelEvent(QWheelEvent *event)
{
if(event->delta() < 0)
scale(1.0/2.0, 1.0/2.0);
else
scale(2, 2);
scene->addRect(scene->itemsBoundingRect());
qDebug() << rect->transform();
qDebug() << rect->boundingRect();
qDebug() << rect2->transform();
qDebug() << rect2->boundingRect();
}
原始视图如下所示: 1
将该线作为道路并将其作为符号放在旁边。缩小时,rect保持其大小但跳出场景: 2
应该是直线到线的中间。我也对调试信息感到困惑,显示boundingRect和transform保持不变,似乎没有任何改变!导致问题的原因是什么方法可以解决?有人可以帮忙吗?谢谢!
答案 0 :(得分:1)
抱歉延迟,现在我自己解决了这个问题。
我发现QGraphicsItem::ItemIgnoresTransformations
只有在您要坚持的点位于项目坐标中的(0,0)时才有效。您还需要以这种方式手动更新boundingRect。然而,我发现的最佳解决方案是子类QGraphicsItem,并根据世界矩阵在paint()中设置矩阵。以下是我的代码。
QMatrix stableMatrix(const QMatrix &matrix, const QPointF &p)
{
QMatrix newMatrix = matrix;
qreal scaleX, scaleY;
scaleX = newMatrix.m11();
scaleY = newMatrix.m22();
newMatrix.scale(1.0/scaleX, 1.0/scaleY);
qreal offsetX, offsetY;
offsetX = p.x()*(scaleX-1.0);
offsetY = p.y()*(scaleY-1.0);
newMatrix.translate(offsetX, offsetY);
return newMatrix;
}
绘画功能:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
QPointF p(left, top);
painter->setMatrix(stableMatrix(painter->worldMatrix(), p));
painter->drawRect(left, top, width, height);
}
stableMatrix的第二个参数是标点,在我的示例代码中它是项目的左上角。您可以根据自己的喜好进行更改。它工作得很好! 希望这篇文章有所帮助:)
答案 1 :(得分:0)
解决方案更简单。
的QGraphicsItem :: ItemIgnoresTransformations
该项目忽略继承的转换(即,其位置仍锚定到其父级,但忽略父级或视图旋转,缩放或剪切转换)。 [...]
这就是关键! Item忽略所有转换,但仍绑定到其父级。所以你需要两个项目:一个父项目将保持相对位置(没有设置任何标志)和一个子项目,它将在父母的上进行绘图(设置QGraphicsItem::ItemIgnoresTransformations
标志)( 0,0)点。
这是一些十字准线的工作代码,它具有恒定的大小和旋转,同时保持与其父级的相对位置:
#include <QGraphicsItem>
#include <QPainter>
class CrossHair : public QGraphicsItem
{
private:
class CrossHairImpl : public QGraphicsItem
{
public:
CrossHairImpl (qreal len, QGraphicsItem *parent = nullptr)
: QGraphicsItem(parent), m_len(len)
{
setFlag(QGraphicsItem::ItemIgnoresTransformations);
}
QRectF boundingRect (void) const override
{
return QRectF(-m_len, -m_len, m_len*2, m_len*2);
}
void paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
painter->setPen(QPen(Qt::red, 1));
painter->drawLine(0, -m_len, 0, m_len);
painter->drawLine(-m_len, 0, m_len, 0);
}
private:
qreal m_len;
};
public:
CrossHair (qreal x, qreal y, qreal len, QGraphicsItem *parent = nullptr)
: QGraphicsItem(parent), m_impl(len, this) // <-- IMPORTANT!!!
{
setPos(x, y);
}
QRectF boundingRect (void) const override
{
return QRectF();
}
void paint (QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override
{
// empty
}
private:
CrossHairImpl m_impl;
};