Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGraphicsItem class itemChange function returns old value
Qt 6.12 LTS is out! See what's new in the release blog

QGraphicsItem class itemChange function returns old value

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 1.6k Views 2 Watching
  • 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.
  • S Offline
    S Offline
    Sridharan
    wrote on last edited by
    #1

    I created QGraphicsRectItem and added to QGraphicsScene. This QGraphicsRectItem has child 'SizeGripItem' which helps to resize it's parent. 'SizeGripItem' has eight child 'HandleItem' (resize handle) and on mouse-press-drag helps to resize QGraphicsRectItem.

    I am able to resize based on itemChange() received by 'HandleItem'. But, my problem is when i do resize operation 2nd time (without deselecting QGraphicsRectItem after 1st resize operation), resize operation begins from older position (i,e) itemChange() function receives old position of 'HandleItem', not new one. Am i missing anything during mouserelease operation

    // sizegripitem.h

    class SizeGripItem : public QGraphicsItem
    {
    private:
    enum
    {
    Top = 0x1,
    Bottom = 0x2,
    Left = 0x4,
    TopLeft = Top | Left,
    BottomLeft = Bottom | Left,
    Right = 0x8,
    TopRight = Top | Right,
    BottomRight = Bottom | Right
    };

    class HandleItem : public QGraphicsEllipseItem
    {
        public:
            HandleItem(int positionFlags, SizeGripItem* parent);
            int positionFlags() const;
    
            void mousePressEvent(QGraphicsSceneMouseEvent *event);
            void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
    
        protected:
            virtual QVariant itemChange(GraphicsItemChange change,
                                        const QVariant &value);
    
        private:
            QPointF restrictPosition(const QPointF& newPos);
    
            void setCursorShape();
    
            int positionFlags_;
            SizeGripItem* parent_;
    };
    

    public:
    class Resizer
    {
    public:
    virtual void operator()(QGraphicsItem* item,
    const QRectF& rect) = 0;
    };

    SizeGripItem(Resizer* resizer = 0, QGraphicsItem* parent = 0);
    virtual ~SizeGripItem();
    virtual QRectF boundingRect() const;
    virtual void paint(QPainter* painter,
                       const QStyleOptionGraphicsItem* option,
                       QWidget* widget = 0);
    void setTopLeft(const QPointF& pos);
    void setTop(qreal y);
    void setTopRight(const QPointF& pos);
    void setRight(qreal x);
    void setBottomRight(const QPointF& pos);
    void setBottom(qreal y);
    void setBottomLeft(const QPointF& pos);
    void setLeft(qreal x);
    
    QRectF rect_;
    void doResize();
    

    private:
    //void doResize();
    void updateHandleItemPositions();

    QList<HandleItem*> handleItems_;
    // QRectF rect_;
    Resizer* resizer_;
    

    };

    //sizegriptem.cpp

    SizeGripItem::HandleItem::HandleItem(int positionFlags, SizeGripItem* parent)
    : QGraphicsEllipseItem(-4, -4, 8, 8, parent),
    positionFlags_(positionFlags),
    parent_(parent)
    {
    setBrush(QBrush(Qt::white));
    setFlag(ItemIsMovable);
    setFlag(ItemSendsGeometryChanges);
    setCursorShape();
    setAcceptHoverEvents(true);
    }

    int SizeGripItem::HandleItem::positionFlags() const
    {
    return positionFlags_;
    }

    QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change,
    const QVariant &value)
    {
    QVariant retVal = value;

    if (change == ItemPositionChange)
    {
        retVal = restrictPosition(value.toPointF());
    }
    else if (change == ItemPositionHasChanged)
    {
        QPointF pos = value.toPointF();
    
        switch (positionFlags_)
        {
            case TopLeft:
                parent_->setTopLeft(pos);
                break;
            case Top:
                parent_->setTop(pos.y());
                break;
            case TopRight:
                parent_->setTopRight(pos);
                break;
            case Right:
                parent_->setRight(pos.x());
                break;
            case BottomRight:
                parent_->setBottomRight(pos);
                break;
            case Bottom:
                parent_->setBottom(pos.y());
                break;
            case BottomLeft:
                parent_->setBottomLeft(pos);
                break;
            case Left:
                parent_->setLeft(pos.x());
                break;
        }
    }
    
    return retVal;
    

    }

    QPointF SizeGripItem::HandleItem::restrictPosition(const QPointF& newPos)
    {
    QPointF retVal = pos();

    if (positionFlags_ & Top || positionFlags_ & Bottom)
        retVal.setY(newPos.y());
    
    if (positionFlags_ & Left || positionFlags_ & Right)
        retVal.setX(newPos.x());
    
    if (positionFlags_ & Top && retVal.y() > parent_->rect_.bottom())
        retVal.setY(parent_->rect_.bottom());
    else if (positionFlags_ & Bottom && retVal.y() < parent_->rect_.top())
        retVal.setY(parent_->rect_.top());
    
    if (positionFlags_ & Left && retVal.x() > parent_->rect_.right())
        retVal.setX(parent_->rect_.right());
    else if (positionFlags_ & Right && retVal.x() < parent_->rect_.left())
        retVal.setX(parent_->rect_.left());
    
    return retVal;
    

    }

    void SizeGripItem::HandleItem::setCursorShape()
    {
    switch (positionFlags_)
    {
    case TopLeft:
    setCursor(Qt::SizeFDiagCursor);
    break;
    case Top:
    setCursor(Qt::SizeVerCursor);
    break;
    case TopRight:
    setCursor(Qt::SizeBDiagCursor);
    break;
    case Right:
    setCursor(Qt::SizeHorCursor);
    break;
    case BottomRight:
    setCursor(Qt::SizeFDiagCursor);
    break;
    case Bottom:
    setCursor(Qt::SizeVerCursor);
    break;
    case BottomLeft:
    setCursor(Qt::SizeBDiagCursor);
    break;
    case Left:
    setCursor(Qt::SizeHorCursor);
    break;
    }
    }

    SizeGripItem::SizeGripItem(Resizer* resizer, QGraphicsItem* parent)
    : QGraphicsItem(parent),
    resizer_(resizer)
    {
    if (parentItem())
    rect_ = parentItem()->boundingRect();

    handleItems_.append(new HandleItem(TopLeft, this));
    handleItems_.append(new HandleItem(Top, this));
    handleItems_.append(new HandleItem(TopRight, this));
    handleItems_.append(new HandleItem(Right, this));
    handleItems_.append(new HandleItem(BottomRight, this));
    handleItems_.append(new HandleItem(Bottom, this));
    handleItems_.append(new HandleItem(BottomLeft, this));
    handleItems_.append(new HandleItem(Left, this));
    updateHandleItemPositions();
    

    }

    SizeGripItem::~SizeGripItem()
    {
    if (resizer_)
    delete resizer_;
    }

    QRectF SizeGripItem::boundingRect() const
    {
    return rect_;
    }

    void SizeGripItem::paint(QPainter* painter,
    const QStyleOptionGraphicsItem* option,
    QWidget* widget)
    {
    }

    #define IMPL_SET_FN(TYPE, POS)
    void SizeGripItem::set ## POS (TYPE v)
    {
    rect_.set ## POS (v);
    doResize();
    }

    IMPL_SET_FN(qreal, Top)
    IMPL_SET_FN(qreal, Right)
    IMPL_SET_FN(qreal, Bottom)
    IMPL_SET_FN(qreal, Left)
    IMPL_SET_FN(const QPointF&, TopLeft)
    IMPL_SET_FN(const QPointF&, TopRight)
    IMPL_SET_FN(const QPointF&, BottomRight)
    IMPL_SET_FN(const QPointF&, BottomLeft)

    void SizeGripItem::doResize()
    {
    if (resizer_)
    {
    (*resizer_)(parentItem(), rect_);
    updateHandleItemPositions();
    }
    }

    void SizeGripItem::updateHandleItemPositions()
    {
    foreach (HandleItem* item, handleItems_)
    {
    item->setFlag(ItemSendsGeometryChanges, false);

        switch (item->positionFlags())
        {
            case TopLeft:
                item->setPos(rect_.topLeft());
                break;
            case Top:
                item->setPos(rect_.left() + rect_.width() / 2 - 1,
                             rect_.top());
                break;
            case TopRight:
                item->setPos(rect_.topRight());
                break;
            case Right:
                item->setPos(rect_.right(),
                             rect_.top() + rect_.height() / 2 - 1);
                break;
            case BottomRight:
                item->setPos(rect_.bottomRight());
                break;
            case Bottom:
                item->setPos(rect_.left() + rect_.width() / 2 - 1,
                             rect_.bottom());
                break;
            case BottomLeft:
                item->setPos(rect_.bottomLeft());
                break;
            case Left:
                item->setPos(rect_.left(),
                             rect_.top() + rect_.height() / 2 - 1);
                break;
        }
    
        item->setFlag(ItemSendsGeometryChanges, true);
    }
    

    }

    void SizeGripItem::HandleItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
    parent_->parentItem()->setFlag(QGraphicsItem::ItemIsMovable, false);
    }

    void SizeGripItem::HandleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
    parent_->parentItem()->setFlag(QGraphicsItem::ItemIsMovable, true);
    }

    // MainWindow.cpp

    namespace
    {
    class RectResizer : public SizeGripItem::Resizer
    {
    public:
    virtual void operator()(QGraphicsItem* item, const QRectF& rect)
    {
    QGraphicsRectItem* rectItem =
    dynamic_cast<QGraphicsRectItem*>(item);

                if (rectItem)
                {
                    rectItem->setRect(rect);
                }
            }
    };
    
    class EllipseResizer : public SizeGripItem::Resizer
    {
        public:
            virtual void operator()(QGraphicsItem* item, const QRectF& rect)
            {
                QGraphicsEllipseItem* ellipseItem =
                    dynamic_cast<QGraphicsEllipseItem*>(item);
    
                if (ellipseItem)
                {
                    ellipseItem->setRect(rect);
                }
            }
    };
    

    }

    MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    QGraphicsView* view = new QGraphicsView(ui->centralwidget);
    view->setGeometry(100, 100, 500, 500);
    view->setFrameStyle(0);  
    
    QGraphicsScene* scene = new QGraphicsScene(0, 0, 500, 500, view);
    scene->setBackgroundBrush(Qt::white);
    view->setScene(scene);
    m_scene = scene;
    
    QGraphicsRectItem* rectItem = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
    rectItem->setBrush(Qt::white);
    rectItem->setFlag(QGraphicsItem::ItemIsMovable);
    rectItem->setFlag(QGraphicsItem::ItemIsSelectable);
    rectItem->setCursor(Qt::SizeAllCursor);
    scene->addItem(rectItem);
    rectItem->setPos(100, 10);
    
    connect(m_scene, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
    
    m_currentSelectedItem = nullptr;
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::selectionChanged()
    {
    qDebug() << "Main window selection change";
    QList<QGraphicsItem *> selectedItems = m_scene->selectedItems();

    if (m_currentSelectedItem != nullptr)
    {
        delete m_currentSelectedItem;
        m_currentSelectedItem = nullptr;
    }
    
    foreach (QGraphicsItem* item, selectedItems)
    {
        QGraphicsRectItem* r = dynamic_cast<QGraphicsRectItem*> (item);
        QGraphicsEllipseItem* e = dynamic_cast<QGraphicsEllipseItem*> (item);
    
        if (r)
        {
            qDebug() << "rect item selected";
            m_currentSelectedItem = new SizeGripItem(new RectResizer, r);
    
        }
        else if (e)
        {
            qDebug() << "ellipse item selected";
            m_currentSelectedItem = new SizeGripItem(new EllipseResizer, e);
        }
    }
    

    }

    JonBJ 1 Reply Last reply
    0
    • S Sridharan

      @Asperamanca

      If parent item moves, child also moves along with parent. So, if I make handle as parent and move the handle for resize, actual shape also moves.

      And here, I have 8 handles for resize operation. We can't make actual shape to child of all 8 handles

      S Offline
      S Offline
      Sridharan
      wrote on last edited by
      #7

      [Solved]

      In mousePressEvent and mouseReleaseEvent function of 'HandleItem' class, forward the call to base class.\

      Add, QGraphicsRectItem::mousePressEvent(event) in mousePressEvent() function and QGraphicsRectItem::mouseReleaseEvent (event) in mouseReleaseEvent() function of 'HandleItem' class

      1 Reply Last reply
      0
      • S Sridharan

        I created QGraphicsRectItem and added to QGraphicsScene. This QGraphicsRectItem has child 'SizeGripItem' which helps to resize it's parent. 'SizeGripItem' has eight child 'HandleItem' (resize handle) and on mouse-press-drag helps to resize QGraphicsRectItem.

        I am able to resize based on itemChange() received by 'HandleItem'. But, my problem is when i do resize operation 2nd time (without deselecting QGraphicsRectItem after 1st resize operation), resize operation begins from older position (i,e) itemChange() function receives old position of 'HandleItem', not new one. Am i missing anything during mouserelease operation

        // sizegripitem.h

        class SizeGripItem : public QGraphicsItem
        {
        private:
        enum
        {
        Top = 0x1,
        Bottom = 0x2,
        Left = 0x4,
        TopLeft = Top | Left,
        BottomLeft = Bottom | Left,
        Right = 0x8,
        TopRight = Top | Right,
        BottomRight = Bottom | Right
        };

        class HandleItem : public QGraphicsEllipseItem
        {
            public:
                HandleItem(int positionFlags, SizeGripItem* parent);
                int positionFlags() const;
        
                void mousePressEvent(QGraphicsSceneMouseEvent *event);
                void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
        
            protected:
                virtual QVariant itemChange(GraphicsItemChange change,
                                            const QVariant &value);
        
            private:
                QPointF restrictPosition(const QPointF& newPos);
        
                void setCursorShape();
        
                int positionFlags_;
                SizeGripItem* parent_;
        };
        

        public:
        class Resizer
        {
        public:
        virtual void operator()(QGraphicsItem* item,
        const QRectF& rect) = 0;
        };

        SizeGripItem(Resizer* resizer = 0, QGraphicsItem* parent = 0);
        virtual ~SizeGripItem();
        virtual QRectF boundingRect() const;
        virtual void paint(QPainter* painter,
                           const QStyleOptionGraphicsItem* option,
                           QWidget* widget = 0);
        void setTopLeft(const QPointF& pos);
        void setTop(qreal y);
        void setTopRight(const QPointF& pos);
        void setRight(qreal x);
        void setBottomRight(const QPointF& pos);
        void setBottom(qreal y);
        void setBottomLeft(const QPointF& pos);
        void setLeft(qreal x);
        
        QRectF rect_;
        void doResize();
        

        private:
        //void doResize();
        void updateHandleItemPositions();

        QList<HandleItem*> handleItems_;
        // QRectF rect_;
        Resizer* resizer_;
        

        };

        //sizegriptem.cpp

        SizeGripItem::HandleItem::HandleItem(int positionFlags, SizeGripItem* parent)
        : QGraphicsEllipseItem(-4, -4, 8, 8, parent),
        positionFlags_(positionFlags),
        parent_(parent)
        {
        setBrush(QBrush(Qt::white));
        setFlag(ItemIsMovable);
        setFlag(ItemSendsGeometryChanges);
        setCursorShape();
        setAcceptHoverEvents(true);
        }

        int SizeGripItem::HandleItem::positionFlags() const
        {
        return positionFlags_;
        }

        QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change,
        const QVariant &value)
        {
        QVariant retVal = value;

        if (change == ItemPositionChange)
        {
            retVal = restrictPosition(value.toPointF());
        }
        else if (change == ItemPositionHasChanged)
        {
            QPointF pos = value.toPointF();
        
            switch (positionFlags_)
            {
                case TopLeft:
                    parent_->setTopLeft(pos);
                    break;
                case Top:
                    parent_->setTop(pos.y());
                    break;
                case TopRight:
                    parent_->setTopRight(pos);
                    break;
                case Right:
                    parent_->setRight(pos.x());
                    break;
                case BottomRight:
                    parent_->setBottomRight(pos);
                    break;
                case Bottom:
                    parent_->setBottom(pos.y());
                    break;
                case BottomLeft:
                    parent_->setBottomLeft(pos);
                    break;
                case Left:
                    parent_->setLeft(pos.x());
                    break;
            }
        }
        
        return retVal;
        

        }

        QPointF SizeGripItem::HandleItem::restrictPosition(const QPointF& newPos)
        {
        QPointF retVal = pos();

        if (positionFlags_ & Top || positionFlags_ & Bottom)
            retVal.setY(newPos.y());
        
        if (positionFlags_ & Left || positionFlags_ & Right)
            retVal.setX(newPos.x());
        
        if (positionFlags_ & Top && retVal.y() > parent_->rect_.bottom())
            retVal.setY(parent_->rect_.bottom());
        else if (positionFlags_ & Bottom && retVal.y() < parent_->rect_.top())
            retVal.setY(parent_->rect_.top());
        
        if (positionFlags_ & Left && retVal.x() > parent_->rect_.right())
            retVal.setX(parent_->rect_.right());
        else if (positionFlags_ & Right && retVal.x() < parent_->rect_.left())
            retVal.setX(parent_->rect_.left());
        
        return retVal;
        

        }

        void SizeGripItem::HandleItem::setCursorShape()
        {
        switch (positionFlags_)
        {
        case TopLeft:
        setCursor(Qt::SizeFDiagCursor);
        break;
        case Top:
        setCursor(Qt::SizeVerCursor);
        break;
        case TopRight:
        setCursor(Qt::SizeBDiagCursor);
        break;
        case Right:
        setCursor(Qt::SizeHorCursor);
        break;
        case BottomRight:
        setCursor(Qt::SizeFDiagCursor);
        break;
        case Bottom:
        setCursor(Qt::SizeVerCursor);
        break;
        case BottomLeft:
        setCursor(Qt::SizeBDiagCursor);
        break;
        case Left:
        setCursor(Qt::SizeHorCursor);
        break;
        }
        }

        SizeGripItem::SizeGripItem(Resizer* resizer, QGraphicsItem* parent)
        : QGraphicsItem(parent),
        resizer_(resizer)
        {
        if (parentItem())
        rect_ = parentItem()->boundingRect();

        handleItems_.append(new HandleItem(TopLeft, this));
        handleItems_.append(new HandleItem(Top, this));
        handleItems_.append(new HandleItem(TopRight, this));
        handleItems_.append(new HandleItem(Right, this));
        handleItems_.append(new HandleItem(BottomRight, this));
        handleItems_.append(new HandleItem(Bottom, this));
        handleItems_.append(new HandleItem(BottomLeft, this));
        handleItems_.append(new HandleItem(Left, this));
        updateHandleItemPositions();
        

        }

        SizeGripItem::~SizeGripItem()
        {
        if (resizer_)
        delete resizer_;
        }

        QRectF SizeGripItem::boundingRect() const
        {
        return rect_;
        }

        void SizeGripItem::paint(QPainter* painter,
        const QStyleOptionGraphicsItem* option,
        QWidget* widget)
        {
        }

        #define IMPL_SET_FN(TYPE, POS)
        void SizeGripItem::set ## POS (TYPE v)
        {
        rect_.set ## POS (v);
        doResize();
        }

        IMPL_SET_FN(qreal, Top)
        IMPL_SET_FN(qreal, Right)
        IMPL_SET_FN(qreal, Bottom)
        IMPL_SET_FN(qreal, Left)
        IMPL_SET_FN(const QPointF&, TopLeft)
        IMPL_SET_FN(const QPointF&, TopRight)
        IMPL_SET_FN(const QPointF&, BottomRight)
        IMPL_SET_FN(const QPointF&, BottomLeft)

        void SizeGripItem::doResize()
        {
        if (resizer_)
        {
        (*resizer_)(parentItem(), rect_);
        updateHandleItemPositions();
        }
        }

        void SizeGripItem::updateHandleItemPositions()
        {
        foreach (HandleItem* item, handleItems_)
        {
        item->setFlag(ItemSendsGeometryChanges, false);

            switch (item->positionFlags())
            {
                case TopLeft:
                    item->setPos(rect_.topLeft());
                    break;
                case Top:
                    item->setPos(rect_.left() + rect_.width() / 2 - 1,
                                 rect_.top());
                    break;
                case TopRight:
                    item->setPos(rect_.topRight());
                    break;
                case Right:
                    item->setPos(rect_.right(),
                                 rect_.top() + rect_.height() / 2 - 1);
                    break;
                case BottomRight:
                    item->setPos(rect_.bottomRight());
                    break;
                case Bottom:
                    item->setPos(rect_.left() + rect_.width() / 2 - 1,
                                 rect_.bottom());
                    break;
                case BottomLeft:
                    item->setPos(rect_.bottomLeft());
                    break;
                case Left:
                    item->setPos(rect_.left(),
                                 rect_.top() + rect_.height() / 2 - 1);
                    break;
            }
        
            item->setFlag(ItemSendsGeometryChanges, true);
        }
        

        }

        void SizeGripItem::HandleItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
        {
        parent_->parentItem()->setFlag(QGraphicsItem::ItemIsMovable, false);
        }

        void SizeGripItem::HandleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
        {
        parent_->parentItem()->setFlag(QGraphicsItem::ItemIsMovable, true);
        }

        // MainWindow.cpp

        namespace
        {
        class RectResizer : public SizeGripItem::Resizer
        {
        public:
        virtual void operator()(QGraphicsItem* item, const QRectF& rect)
        {
        QGraphicsRectItem* rectItem =
        dynamic_cast<QGraphicsRectItem*>(item);

                    if (rectItem)
                    {
                        rectItem->setRect(rect);
                    }
                }
        };
        
        class EllipseResizer : public SizeGripItem::Resizer
        {
            public:
                virtual void operator()(QGraphicsItem* item, const QRectF& rect)
                {
                    QGraphicsEllipseItem* ellipseItem =
                        dynamic_cast<QGraphicsEllipseItem*>(item);
        
                    if (ellipseItem)
                    {
                        ellipseItem->setRect(rect);
                    }
                }
        };
        

        }

        MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
        {
        ui->setupUi(this);

        QGraphicsView* view = new QGraphicsView(ui->centralwidget);
        view->setGeometry(100, 100, 500, 500);
        view->setFrameStyle(0);  
        
        QGraphicsScene* scene = new QGraphicsScene(0, 0, 500, 500, view);
        scene->setBackgroundBrush(Qt::white);
        view->setScene(scene);
        m_scene = scene;
        
        QGraphicsRectItem* rectItem = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
        rectItem->setBrush(Qt::white);
        rectItem->setFlag(QGraphicsItem::ItemIsMovable);
        rectItem->setFlag(QGraphicsItem::ItemIsSelectable);
        rectItem->setCursor(Qt::SizeAllCursor);
        scene->addItem(rectItem);
        rectItem->setPos(100, 10);
        
        connect(m_scene, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
        
        m_currentSelectedItem = nullptr;
        

        }

        MainWindow::~MainWindow()
        {
        delete ui;
        }

        void MainWindow::selectionChanged()
        {
        qDebug() << "Main window selection change";
        QList<QGraphicsItem *> selectedItems = m_scene->selectedItems();

        if (m_currentSelectedItem != nullptr)
        {
            delete m_currentSelectedItem;
            m_currentSelectedItem = nullptr;
        }
        
        foreach (QGraphicsItem* item, selectedItems)
        {
            QGraphicsRectItem* r = dynamic_cast<QGraphicsRectItem*> (item);
            QGraphicsEllipseItem* e = dynamic_cast<QGraphicsEllipseItem*> (item);
        
            if (r)
            {
                qDebug() << "rect item selected";
                m_currentSelectedItem = new SizeGripItem(new RectResizer, r);
        
            }
            else if (e)
            {
                qDebug() << "ellipse item selected";
                m_currentSelectedItem = new SizeGripItem(new EllipseResizer, e);
            }
        }
        

        }

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #2

        @Sridharan
        Hello and welcome.

        Could you post some kind of minimal reproducible example of your problem?

        S 1 Reply Last reply
        0
        • A Offline
          A Offline
          Asperamanca
          wrote on last edited by
          #3

          @Sridharan said in QGraphicsItem class itemChange function returns old value:

          switch (positionFlags_)
          {
          case TopLeft:
          parent_->setTopLeft(pos);
          break;

          Does setting position on parent inside ItemChange maybe trigger a recursive call? When you hit a breakpoint where you have the "old" position, check the call stack for recursive itemChange calls.

          1 Reply Last reply
          0
          • JonBJ JonB

            @Sridharan
            Hello and welcome.

            Could you post some kind of minimal reproducible example of your problem?

            S Offline
            S Offline
            Sridharan
            wrote on last edited by Sridharan
            #4

            @JonB

            I have added QGraphicsRectItem to scene.

            On selecting QGraphicsRectItem, I add few childs to QGraphicsRectItem which helps to achieve resize operation. On deselect, i delete the childs. I have shown below the parent-child relationship

                                 QGraphicsRectItem
                                    |
                                    |- SizeGripItem    
                                        |
                                        |- HandleItem1 (Top)
                                        |- HandleItem 2 (Top left)
                                        |- HandleItem 3 (top right)
                                        |- HandleItem 4 (bottom)
                                        |- HandleItem 5 (bottom left)
                                        |- HandleItem 6 (bottom right)
                                        |- HandleItem 7 (left)
                                        |- HandleItem 8 (right)
            

            SizeGripItem - inherits QGraphicsItem. It's bounding box same as its parent
            HandleItem - This is resizer. On select and drag this item, i resize the boundingbox of QGraphicsRectItem.

            Steps to reproduce problem :

            1. Select QGraphicsRectItem, 8 HandleItem appears for resize operation.
            2. Assume, perform left-button mousepress and drag HandleItem1 for 10px. itemChange() function gets called and provides distance moved (value parameter of function). In this function, based on distance movement, logic is added QGraphicsRectItem to expand. Mouse left-button released. Now rectangle size gets increased. Until here, it works as expected.
            3. Again perform left-button mousepress and drag HandleItem1 for 5px. itemChange() function gets called and provides distance moved from older size. 10px movement performed in step 2) is not considered

            Work around

            After every resize operation, perform left-button mouse press. It works fine.

            Resize--> Left mouse button press on QGraphics rect Item --> Resize --> Left mouse button press on QGraphics rect Item --> Resize

            rectresize.PNG

            A 1 Reply Last reply
            0
            • S Sridharan

              @JonB

              I have added QGraphicsRectItem to scene.

              On selecting QGraphicsRectItem, I add few childs to QGraphicsRectItem which helps to achieve resize operation. On deselect, i delete the childs. I have shown below the parent-child relationship

                                   QGraphicsRectItem
                                      |
                                      |- SizeGripItem    
                                          |
                                          |- HandleItem1 (Top)
                                          |- HandleItem 2 (Top left)
                                          |- HandleItem 3 (top right)
                                          |- HandleItem 4 (bottom)
                                          |- HandleItem 5 (bottom left)
                                          |- HandleItem 6 (bottom right)
                                          |- HandleItem 7 (left)
                                          |- HandleItem 8 (right)
              

              SizeGripItem - inherits QGraphicsItem. It's bounding box same as its parent
              HandleItem - This is resizer. On select and drag this item, i resize the boundingbox of QGraphicsRectItem.

              Steps to reproduce problem :

              1. Select QGraphicsRectItem, 8 HandleItem appears for resize operation.
              2. Assume, perform left-button mousepress and drag HandleItem1 for 10px. itemChange() function gets called and provides distance moved (value parameter of function). In this function, based on distance movement, logic is added QGraphicsRectItem to expand. Mouse left-button released. Now rectangle size gets increased. Until here, it works as expected.
              3. Again perform left-button mousepress and drag HandleItem1 for 5px. itemChange() function gets called and provides distance moved from older size. 10px movement performed in step 2) is not considered

              Work around

              After every resize operation, perform left-button mouse press. It works fine.

              Resize--> Left mouse button press on QGraphics rect Item --> Resize --> Left mouse button press on QGraphics rect Item --> Resize

              rectresize.PNG

              A Offline
              A Offline
              Asperamanca
              wrote on last edited by
              #5

              @Sridharan
              I recommend making the handles toplevel items, instead of children of the item you want to resize.
              This prevents recursion in the logic. Your only extra job is to ensure the handles are initially at the correct position. Then let the user drag them around, and calculate the new size of the parent.
              Resizing the parent now won't affect the handles in any way. Much simpler.

              S 1 Reply Last reply
              0
              • A Asperamanca

                @Sridharan
                I recommend making the handles toplevel items, instead of children of the item you want to resize.
                This prevents recursion in the logic. Your only extra job is to ensure the handles are initially at the correct position. Then let the user drag them around, and calculate the new size of the parent.
                Resizing the parent now won't affect the handles in any way. Much simpler.

                S Offline
                S Offline
                Sridharan
                wrote on last edited by
                #6

                @Asperamanca

                If parent item moves, child also moves along with parent. So, if I make handle as parent and move the handle for resize, actual shape also moves.

                And here, I have 8 handles for resize operation. We can't make actual shape to child of all 8 handles

                S 1 Reply Last reply
                0
                • S Sridharan

                  @Asperamanca

                  If parent item moves, child also moves along with parent. So, if I make handle as parent and move the handle for resize, actual shape also moves.

                  And here, I have 8 handles for resize operation. We can't make actual shape to child of all 8 handles

                  S Offline
                  S Offline
                  Sridharan
                  wrote on last edited by
                  #7

                  [Solved]

                  In mousePressEvent and mouseReleaseEvent function of 'HandleItem' class, forward the call to base class.\

                  Add, QGraphicsRectItem::mousePressEvent(event) in mousePressEvent() function and QGraphicsRectItem::mouseReleaseEvent (event) in mouseReleaseEvent() function of 'HandleItem' class

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt
                  • Unsolved