应用QGraphicsItem :: ItemIgnoresTransformations后维护相对子位置

KD0*_*D07 8 qt qt4 qgraphicsview

我有一个QGraphicsTextItem作为QGraphicsItem的父级.我想QGraphicsTextItem总是直接驻留在的QGraphicsItem以上,但我也希望文本保持相同的大小时,比例因子低于1,即文本保持它在1的比例因子的大小,即使父图形item缩小了.我发现QGraphicsItem::ItemIgnoresTransformations当比例因子低于1时将标志设置为true可以保留大小.

但我似乎无法找到一种方法来使文本的位置始终保持在QGraphicsItem之上.有没有办法做到这一点?我尝试使用deviceTransform ()函数,但是当我滚动时,文本仍然从QGraphicsItem移开.更糟糕的是,一些文本项目开始"摇晃",即他们开始不断地改变他们的位置,所以它看起来像是在颤抖.如果这是我需要使用的功能,我想我不知道如何正确使用它.

在我的QGraphicsItem的构造函数中,我添加了一个QGraphicsTextItem:

fTextItem = new QGraphicsTextItem(getName(), this);
fTextItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
Run Code Online (Sandbox Code Playgroud)

这是QGraphicsItem的paint函数的代码片段

qreal lod = painter->worldTransform().m22();
if(lod <= 1.0) {
     fTextItem-setFlag(QGraphicsItem::ItemIgnoresTransformations);
     fTextItem->setPos(fTextItem->deviceTransform(view-viewportTransform()).inverted().map(view->mapFromScene(mapToScene(0,0))));
} else {
     fTextItem->setFlag(QGraphicsItem::ItemIgnoresTransformations, false);
     fTextItem->setPos(0, 0);
}
Run Code Online (Sandbox Code Playgroud)

小智 6

我的建议是以这种方式子类化QGraphicsSimpleTextItem:

class TextItem
    : public QGraphicsSimpleTextItem
{
public:
    TextItem(const QString &text)
        : QGraphicsSimpleTextItem(text)
    {

    }
    void paint(QPainter *painter, 
        const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->translate(boundingRect().topLeft());
        QGraphicsSimpleTextItem::paint(painter, option, widget);
        painter->translate(-boundingRect().topLeft());
    }
    QRectF boundingRect() const
    {
        QRectF b = QGraphicsSimpleTextItem::boundingRect();
        return QRectF(b.x()-b.width()/2.0, b.y()-b.height()/2.0, 
            b.width(), b.height());
    }
};
QGraphicsSimpleTextItem *mText = new TextItem("Item");
scene()->addItem(mText);
mText->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
mText->setPos(itemToFollow->pos());
Run Code Online (Sandbox Code Playgroud)


Dav*_*eer 4

免责声明:这对于您想要做的事情来说可能有点过分了。我们的项目中有一些额外的限制,这使得这个解决方案对我们来说最简单。

我们必须在项目中做类似的事情,最终我们最容易不使用ItemIgnoresTransformations而是推出我们自己的转换。这是我们用来创建仅平移(无缩放)变换以在特定位置绘制项目的主要函数。您也许可以根据自己的用途修改它。

static QTransform GenerateTranslationOnlyTransform(
    const QTransform &original_transform,
    const QPointF &target_point) {
  // To draw the unscaled icons, we desire a transform with scaling factors
  // of 1 and shearing factors of 0 and the appropriate translation such that
  // our icon center ends up at the same point. According to the
  // documentation, QTransform transforms a point in the plane to another
  // point using the following formulas:
  // x' = m11*x + m21*y + dx
  // y' = m22*y + m12*x + dy
  //
  // For our new transform, m11 and m22 (scaling) are 1, and m21 and m12
  // (shearing) are 0. Since we want x' and y' to be the same, we have the
  // following equations:
  // m11*x + m21*y + dx = x + dx[new]
  // m22*y + m12*x + dy = y + dy[new]
  //
  // Thus,
  // dx[new] = m11*x - x + m21*y + dx
  // dy[new] = m22*y - y + m12*x + dy
  qreal dx = original_transform.m11() * target_point.x()
             - target_point.x()
             + original_transform.m21() * target_point.y()
             + original_transform.m31();
  qreal dy = original_transform.m22() * target_point.y()
             - target_point.y()
             + original_transform.m12() * target_point.x()
             + original_transform.m32();

  return QTransform::fromTranslate(dx, dy);
}
Run Code Online (Sandbox Code Playgroud)

要使用,请获取QPainter传递给 Paint 方法的转换并执行以下操作:

painter->save();
painter->setTransform(GenerateTranslationOnlyTransform(painter->transform(),
                                                       some_point));
// Draw your item.
painter->restore();
Run Code Online (Sandbox Code Playgroud)