Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsItem::ItemIgnoresTransformations issue
QtWS25 Last Chance

QGraphicsItem::ItemIgnoresTransformations issue

Scheduled Pinned Locked Moved Unsolved General and Desktop
graphicsitemgraphcisview
2 Posts 2 Posters 2.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mammamia
    wrote on 2 Aug 2016, 10:54 last edited by Mammamia 8 Feb 2016, 10:57
    #1

    I am trying to create an custom Arrow item by deriving from QGraphicsLineItem and using a QGraphicsPolygonItem for arrow head.

    I want to use the same size for arrow head across the zoom levels so I have used flag "ItemIgnoresTransformations" but when i change the zoom value other that 1.0 then I could see that the arrow head is drawing at wrong position.

    Please see my test app below.

    const qreal Pi = 3.14;
    /// RotateHandleItem class
    class RotateHandleItem : public QGraphicsLineItem
    {
    public:
      RotateHandleItem(QGraphicsItem* parent = nullptr)
        : QGraphicsLineItem(parent),
          m_Parent(parent)
      {
        this->setAcceptHoverEvents(true);
        setFlag(ItemSendsGeometryChanges);
        setFlag(ItemIsMovable);
    
        m_ArrowHedItem = new QGraphicsPolygonItem(this);
        m_ArrowHedItem->setFlag(QGraphicsItem::ItemIgnoresTransformations);
      }
    
      QRectF boundingRect()
      {
        QRectF rect = shape().boundingRect();
        // add a few extra pixels for the arrow and the pen
        qreal penWidth = 1;
        qreal extra = (penWidth + 6) / 2.0;
        rect.adjust(-extra, -extra, extra, extra);
        return rect;
      }
      QPainterPath shape()
      {
        QPainterPath path = QGraphicsLineItem::shape();
        path.addPolygon(m_ArrowHead);
        return path;
      }
    
      void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
      {
        Q_UNUSED(option);
        Q_UNUSED(widget);
    
        double angle = ::acos(line().dx() / line().length());
        if (line().dy() >= 0)
          angle = (Pi * 2) - angle;
    
        QPointF arrowP1;
        QPointF arrowP2;
        qreal arrowSize = 10;
    
        m_ArrowHead.clear();
        m_ArrowHead << line().p2();
        arrowP1 = line().p2() - QPointF(sin(angle + Pi / 3) * arrowSize,
                                        cos(angle + Pi / 3) * arrowSize);
        arrowP2 = line().p2() - QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
                                        cos(angle + Pi - Pi / 3) * arrowSize);
        m_ArrowHead << arrowP1 << arrowP2;
    
        QPen pen;
        pen.setWidth(1);
        pen.setCosmetic(true);
        pen.setColor(QColor(255, 204, 0));
        painter->setPen(pen);
        m_ArrowHedItem->setPen(pen);
        m_ArrowHedItem->setBrush(Qt::black);
        m_ArrowHedItem->setPolygon(m_ArrowHead);  //Arrow Head
        painter->drawLine(line());  //Arrow Line
      }
    
    private:
      QGraphicsItem* m_Parent;
      QPolygonF m_ArrowHead;
      QGraphicsPolygonItem* m_ArrowHedItem;
    };
    
    int main(int argc, char *argv[])
    {
      QApplication a(argc, argv);
    
      QGraphicsView view;
      QGraphicsScene scene;
      view.setScene(&scene);
      view.scale(2.0, 2.0);
    
      RotateHandleItem* m_RotateHandle = new RotateHandleItem();
      m_RotateHandle->setLine(100, 100, 200, 100);
      scene.addItem(m_RotateHandle);
    
      view.showMaximized();
      return a.exec();
    }
    

    In second last line of method paint() I am setting the calculated Arrow head polygon value to PolygonItem.

    I have also tried to set the polygon value after converting it using mapToParent() but didn't help. I feel like I am missing something here.

    Please help me to solve this issue.

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Asperamanca
      wrote on 2 Aug 2016, 13:27 last edited by
      #2

      You move the arrow head by changing the coordinates within the polygon itself, instead of moving the whole arrow head

      (To illustrate: Let's say your arrowhead item is a piece of paper. The polygon within is a triangle you scribble on the paper. When you want to move the triangle, you can (a) move the paper, or (b) keep the paper where it is, but scribble the triangle in a different part of the paper)

      Your RotateHandleItem is affected by the zoom. Now you use coordinates from within that object to determine the polygon for the arrow head. That way, you go over coordinate system boundaries without correctly mapping the coordinates.

      Easier way: Assign the arrow head a fixed polygon, and use the setPos method to move it to the correct position.

      1 Reply Last reply
      0

      1/2

      2 Aug 2016, 10:54

      • Login

      • Login or register to search.
      1 out of 2
      • First post
        1/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved