2016-11-14 1278 views
2

我在QGraphicsScene中有一些QGraphicsItems,在縮放時應該保持相同的大小和位置。我試過QGraphicsItem :: ItemIgnoresTransformations,但事實證明,項目得到錯誤的立場。下面是一個示例代碼:如何在縮放視圖時保持QGraphicsItem的大小和位置?

我有子類的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

以路線作爲道路,並將其作爲標誌放在一邊。當縮小時,矩形保持其大小,但跳出場景: 2

這應該是指令中間行的矩形。我也混淆了調試信息,顯示boundingRect和transform保持不變,這似乎沒有任何改變!是什麼導致了這個問題,有什麼辦法可以解決它?有人可以幫忙嗎?謝謝!

回答

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的第二個參數是貼一點,在我的示例代碼是左上角的項目。您可以將其更改爲您的偏好。它工作得很好! 希望本帖子幫助:)

0

對此的解決方案更簡單。

的QGraphicsItem :: ItemIgnoresTransformations

項忽略繼承變換(即,其位置仍錨定在其母體,但父或視圖旋轉,縮放或剪切變換被忽略)。 [...]

而這就是關鍵! Item忽略所有轉換,但仍然綁定到其父項。因此,您需要兩個項目:一個將保留相對位置(未設置任何標誌)的父項目以及將在父級(0,0)點處執行圖形(使用QGraphicsItem::ItemIgnoresTransformations標誌設置)的子項目。

這裏是有一定的大小和旋轉十字的一些工作代碼,同時保持相對位置,其父:

#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; 
}; 
相關問題