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. Problem with resizing when object is rotated

Problem with resizing when object is rotated

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 2 Posters 407 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.
  • O Offline
    O Offline
    ollax452
    wrote on last edited by
    #1

    Hi!
    I have a text-box/rectangle with corner-grabbers to enable to change width & height (draggable corners). But after a rotation/transform the re-size does not works as expected. When dragging the corners I want the oppsite corner to be stucked/not moving as it does when the text-box is not rotated. Please can some have a look at it and give me some advices.

    Best Regards
    Olle

    This function is used to rotate the textbox:

    void StateBox::rotate(qreal angle)
    {
        setTransformOriginPoint(boundingRect().center());
        setRotation(45);
    }
    
    

    textbox rotated.png

    statebox.cpp file:

    #include "statebox.h"
    
    #include <QBrush>
    #include <QLinearGradient>
    #include <QDebug>
    
    #include "math.h"
    
    StateBox::StateBox():
            _text(),
            _outterborderColor(Qt::black),
            _outterborderPen(),
            _location(0,0),
            _dragStart(0,0),
            _gridSpace(10),
            _width(250),
            _height(200),
            _cornerDragStart(0,0),
            _XcornerGrabBuffer(20),
            _YcornerGrabBuffer(20),
            _drawingWidth(  _width -   _XcornerGrabBuffer),
            _drawingHeight( _height -  _YcornerGrabBuffer),
            _drawingOrigenX( _XcornerGrabBuffer),
            _drawingOrigenY( _YcornerGrabBuffer)
    {
    
        _outterborderPen.setWidth(2);
        _outterborderPen.setColor(_outterborderColor);
    
        _text.setPos(35,35);
        _text.setPlainText("text goes here");
        _text.setParentItem(this);
    
        this->setAcceptHoverEvents(true);
    }
    
    void StateBox::adjustSize(int x, int y)
    {
        _width += x;
        _height += y;
        _drawingWidth =  _width - _XcornerGrabBuffer;
        _drawingHeight=  _height - _YcornerGrabBuffer;
    }
    
    bool StateBox::sceneEventFilter ( QGraphicsItem * watched, QEvent * event )
    {
        qDebug() << " QEvent == " + QString::number(event->type());
    
        CornerGrabber * corner = dynamic_cast<CornerGrabber *>(watched);
        if ( corner == NULL) return false; // not expected to get here
    
        QGraphicsSceneMouseEvent * mevent = dynamic_cast<QGraphicsSceneMouseEvent*>(event);
        if ( mevent == NULL)
        {
            // this is not one of the mouse events we are interrested in
            return false;
        }
    
        switch (event->type() )
        {
                // if the mouse went down, record the x,y coords of the press, record it inside the corner object
            case QEvent::GraphicsSceneMousePress:
                {
                    corner->setMouseState(CornerGrabber::kMouseDown);
                    corner->mouseDownX = mevent->pos().x();
                    corner->mouseDownY = mevent->pos().y();
                }
                break;
    
            case QEvent::GraphicsSceneMouseRelease:
                {
                    corner->setMouseState(CornerGrabber::kMouseReleased);
    
                }
                break;
    
            case QEvent::GraphicsSceneMouseMove:
                {
                    corner->setMouseState(CornerGrabber::kMouseMoving );
                }
                break;
    
            default:
                // we dont care about the rest of the events
                return false;
                break;
        }
    
        if ( corner->getMouseState() == CornerGrabber::kMouseMoving )
        {
            qreal x = mevent->pos().x(), y = mevent->pos().y();
    
            // depending on which corner has been grabbed, we want to move the position
            // of the item as it grows/shrinks accordingly. so we need to eitehr add
            // or subtract the offsets based on which corner this is.
    
            int XaxisSign = 0;
            int YaxisSign = 0;
            switch( corner->getCorner() )
            {
            case 0:
                {
                    XaxisSign = +1;
                    YaxisSign = +1;
                }
                break;
    
            case 1:
                {
                    XaxisSign = -1;
                    YaxisSign = +1;
                }
                break;
    
            case 2:
                {
                    XaxisSign = -1;
                    YaxisSign = -1;
                }
                break;
    
            case 3:
                {
                    XaxisSign = +1;
                    YaxisSign = -1;
                }
                break;
    
            }
    
            // if the mouse is being dragged, calculate a new size and also re-position
            // the box to give the appearance of dragging the corner out/in to resize the box
    
            int xMoved = corner->mouseDownX - x;
            int yMoved = corner->mouseDownY - y;
    
            int newWidth = _width + ( XaxisSign * xMoved);
            if ( newWidth < 40 ) newWidth  = 40;
    
            int newHeight = _height + (YaxisSign * yMoved) ;
            if ( newHeight < 40 ) newHeight = 40;
    
            int deltaWidth  =   newWidth - _width ;
            int deltaHeight =   newHeight - _height ;
    
            adjustSize(  deltaWidth ,   deltaHeight);
    
            deltaWidth *= (-1);
            deltaHeight *= (-1);
    
            if ( corner->getCorner() == 0 )
            {
                int newXpos = this->pos().x() + deltaWidth;
                int newYpos = this->pos().y() + deltaHeight;
                this->setPos(newXpos, newYpos);
            }
            else   if ( corner->getCorner() == 1 )
            {
                int newYpos = this->pos().y() + deltaHeight;
                this->setPos(this->pos().x(), newYpos);
            }
            else   if ( corner->getCorner() == 3 )
            {
                int newXpos = this->pos().x() + deltaWidth;
                this->setPos(newXpos,this->pos().y());
            }
    
            setCornerPositions();
    
            this->update();
        }
    
        return true;// true => do not send event to watched - we are finished with this event
    }
    
    // for supporting moving the box across the scene
    void StateBox::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
    {
        event->setAccepted(true);
        _location.setX( ( static_cast<int>(_location.x()) / _gridSpace) * _gridSpace );
        _location.setY( ( static_cast<int>(_location.y()) / _gridSpace) * _gridSpace );
        this->setPos(_location);
    }
    
    
    // for supporting moving the box across the scene
    void StateBox::mousePressEvent ( QGraphicsSceneMouseEvent * event )
    {
        event->setAccepted(true);
        _dragStart = event->pos();
    }
    
    
    // for supporting moving the box across the scene
    void StateBox::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
    {
        QPointF newPos = event->pos() ;
        _location += (newPos - _dragStart);
        this->setPos(_location);
    }
    
    // remove the corner grabbers
    void StateBox::hoverLeaveEvent ( QGraphicsSceneHoverEvent * )
    {
        _outterborderColor = Qt::black;
    
        _corners[0]->setParentItem(NULL);
        _corners[1]->setParentItem(NULL);
        _corners[2]->setParentItem(NULL);
        _corners[3]->setParentItem(NULL);
    
        delete _corners[0];
        delete _corners[1];
        delete _corners[2];
        delete _corners[3];
    }
    
    // create the corner grabbers
    void StateBox::hoverEnterEvent ( QGraphicsSceneHoverEvent * )
    {
        _outterborderColor = Qt::red;
    
        _corners[0] = new CornerGrabber(this,0);
        _corners[1] = new CornerGrabber(this,1);
        _corners[2] = new CornerGrabber(this,2);
        _corners[3] = new CornerGrabber(this,3);
    
    
        _corners[0]->installSceneEventFilter(this);
        _corners[1]->installSceneEventFilter(this);
        _corners[2]->installSceneEventFilter(this);
        _corners[3]->installSceneEventFilter(this);
    
        setCornerPositions();
    
    }
    
    void StateBox::setCornerPositions()
    {
        _corners[0]->setPos(_drawingOrigenX, _drawingOrigenY);
        _corners[1]->setPos(_drawingWidth,  _drawingOrigenY);
        _corners[2]->setPos(_drawingWidth , _drawingHeight);
        _corners[3]->setPos(_drawingOrigenX, _drawingHeight);
    }
    
    QRectF StateBox::boundingRect() const
    {
        return QRectF(0,0,_width,_height);
    }
    
    void StateBox::paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        int shadowThickness = 3;
    
        QLinearGradient gradient;
        gradient.setStart(_drawingOrigenX,_drawingOrigenY);
        gradient.setFinalStop( _drawingWidth ,_drawingOrigenY);
        QColor grey1(150,150,150,125);// starting color of the gradient - can play with the starting color and ,point since its not visible anyway
    
        // grey2 is ending color of the gradient - this is what will show up as the shadow. the last parameter is the alpha blend, its set
        // to 125 allowing a mix of th color and and the background, making more realistic shadow effect.
        QColor grey2(225,225,225,125);
    
    
        gradient.setColorAt((qreal)0, grey1 );
        gradient.setColorAt((qreal)1, grey2 );
    
        QBrush brush(gradient);
    
        painter->setBrush( brush);
    
        // for the desired effect, no border will be drawn, and because a brush was set, the drawRoundRect will fill the box with the gradient brush.
        _outterborderPen.setStyle(Qt::NoPen);
        painter->setPen(_outterborderPen);
    
        QPointF topLeft (_drawingOrigenX,_drawingOrigenX);
        QPointF bottomRight ( _drawingWidth , _drawingHeight);
    
        QRectF rect (topLeft, bottomRight);
    
        painter->drawRoundRect(rect,25,25); // corner radius of 25 pixels
    
        // draw the top box, the visible one
        QBrush brush2(QColor(243,255,216,255),Qt::SolidPattern);
    
        painter->setBrush( brush2);
    
        QPointF topLeft2 (_drawingOrigenX, _drawingOrigenY);
        QPointF bottomRight2 ( _drawingWidth-shadowThickness, _drawingHeight-shadowThickness);
    
        QRectF rect2 (topLeft2, bottomRight2);
    
        painter->drawRoundRect(rect2,25,25);
    
    }
    
    void StateBox::mouseMoveEvent(QGraphicsSceneDragDropEvent *event)
    {
        event->setAccepted(false);
    }
    
    void StateBox::mousePressEvent(QGraphicsSceneDragDropEvent *event)
    {
        event->setAccepted(false);
    }
    
    void StateBox::rotate(qreal angle)
    {
        setTransformOriginPoint(boundingRect().center());
        setRotation(45);
    }
    

    statebox.h

    #ifndef STATEBOX_H
    #define STATEBOX_H
    
    #include <QGraphicsItem>
    #include <QGraphicsRectItem>
    #include <QGraphicsTextItem>
    #include <QGraphicsSceneHoverEvent>
    #include <QGraphicsSceneMouseEvent>
    #include <QColor>
    #include <QPainter>
    #include <QPen>
    #include <QPointF>
    #include "cornergrabber.h"
    
    class StateBox : public QGraphicsItem
    {
    public:
        StateBox();
        QGraphicsTextItem _text;    ///< sample text to go in the title area.
    
        void setGridSpace(int space);
        void rotate(qreal angle);
    
        private:
    
    
        virtual QRectF boundingRect() const; ///< must be re-implemented in this class to provide the diminsions of the box to the QGraphicsView
        virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ///< must be re-implemented here to pain the box on the paint-event
        virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover enter events
        virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover leave events
    
        virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );///< allows the main object to be moved in the scene by capturing the mouse move events
        virtual void mousePressEvent (QGraphicsSceneMouseEvent * event );
        virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event );
    
        virtual void mouseMoveEvent(QGraphicsSceneDragDropEvent *event);
        virtual void mousePressEvent(QGraphicsSceneDragDropEvent *event);
        virtual bool sceneEventFilter ( QGraphicsItem * watched, QEvent * event ) ;
    
        void setCornerPositions();
        void adjustSize(int x, int y);
    
    
        QColor _outterborderColor; ///< the hover event handlers will toggle this between red and black
        QPen _outterborderPen; ///< the pen is used to paint the red/black border
        QPointF _location;
        QPointF _dragStart;
        int     _gridSpace;
        qreal   _width;
        qreal   _height;
    
        QPointF _cornerDragStart;
    
        int _XcornerGrabBuffer;
        int _YcornerGrabBuffer;
        qreal   _drawingWidth;
        qreal   _drawingHeight;
        qreal   _drawingOrigenX;
        qreal   _drawingOrigenY;
    
        CornerGrabber*  _corners[4];// 0,1,2,3  - starting at x=0,y=0 and moving clockwise around the box
    };
    
    #endif // STATEBOX_H
    

    cornergrabber.cpp

    #include "cornergrabber.h"
    
    CornerGrabber::CornerGrabber(QGraphicsItem *parent,  int corner) :
        QGraphicsItem(parent),
        mouseDownX(0),
        mouseDownY(0),
        _outterborderColor(Qt::black),
        _outterborderPen(),
        _width(6),
        _height(6),
        _corner(corner),
        _mouseButtonState(kMouseReleased)
    {
        setParentItem(parent);
    
        _outterborderPen.setWidth(2);
        _outterborderPen.setColor(_outterborderColor);
    
       this->setAcceptHoverEvents(true);
    }
    
    void CornerGrabber::setMouseState(int s)
    {
        _mouseButtonState = s;
    }
    
    int CornerGrabber::getMouseState()
    {
        return _mouseButtonState;
    }
    
    int CornerGrabber::getCorner()
    {
        return _corner;
    }
    
    void CornerGrabber::mouseMoveEvent(QGraphicsSceneDragDropEvent *event)
    {
        event->setAccepted(false);
    }
    
    void CornerGrabber::mousePressEvent(QGraphicsSceneDragDropEvent *event)
    {
        event->setAccepted(false);
    }
    
    void CornerGrabber::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
    {
        event->setAccepted(true);
    }
    
    void CornerGrabber::mousePressEvent ( QGraphicsSceneMouseEvent * event )
    {
        event->setAccepted(false);
    }
    
    void CornerGrabber::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
    {
        event->setAccepted(false);
    }
    
    void CornerGrabber::hoverLeaveEvent ( QGraphicsSceneHoverEvent * )
    {
        _outterborderColor = Qt::black;
        this->update(0,0,_width,_height);
    }
    
    void CornerGrabber::hoverEnterEvent ( QGraphicsSceneHoverEvent * )
    {
        _outterborderColor = Qt::red;
        this->update(0,0,_width,_height);
    }
    
    QRectF CornerGrabber::boundingRect() const
    {
        return QRectF(0,0,_width,_height);
    }
    
    void CornerGrabber::paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        _outterborderPen.setCapStyle(Qt::SquareCap);
        _outterborderPen.setStyle(Qt::SolidLine);
        painter->setPen(_outterborderPen);
    
        QPointF topLeft (0, 0);
        QPointF bottomRight ( _width, _height);
    
        QRectF rect (topLeft, bottomRight);
    
        QBrush brush (Qt::SolidPattern);
        brush.setColor (_outterborderColor);
        painter->fillRect(rect,brush);
    
    }
    
    

    cornergrabber.h

    #ifndef CORNERGRABBER_H
    #define CORNERGRABBER_H
    
    #include <QObject>
    #include <QGraphicsItem>
    #include <QGraphicsRectItem>
    #include <QGraphicsTextItem>
    #include <QGraphicsSceneHoverEvent>
    #include <QGraphicsSceneMouseEvent>
    #include <QColor>
    #include <QPainter>
    #include <QPen>
    #include <QPointF>
    
    class CornerGrabber : public QGraphicsItem
    {
    
    public:
        explicit CornerGrabber(QGraphicsItem *parent = 0,  int corner=0);
    
        int  getCorner(); ///< allows the owner to find out which coner this is
        void setMouseState(int); ///< allows the owner to record the current mouse state
        int  getMouseState(); ///< allows the owner to get the current mouse state
    
        qreal mouseDownX;
        qreal mouseDownY;
    
         enum {kMouseReleased=0, kMouseDown, kMouseMoving}; ///< define the mouse states
    
    private:
    
        virtual QRectF boundingRect() const; ///< must be re-implemented in this class to provide the diminsions of the box to the QGraphicsView
        virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ///< must be re-implemented here to pain the box on the paint-event
        virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover enter events
        virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover leave events
        virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
        virtual void mouseMoveEvent(QGraphicsSceneDragDropEvent *event);
        virtual void mousePressEvent (QGraphicsSceneMouseEvent * event );
        virtual void mousePressEvent(QGraphicsSceneDragDropEvent *event);
        virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event );
    
        QColor _outterborderColor; ///< the hover event handlers will toggle this between red and black
        QPen _outterborderPen; ///< the pen is used to paint the red/black border
    
        qreal   _width;
        qreal   _height;
    
        int _corner;// 0,1,2,3  - starting at x=0,y=0 and moving clockwise around the box
        int _mouseButtonState;
    };
    
    #endif // CORNERGRABBER_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    #include <QSizePolicy>
    #include <QGraphicsLineItem>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow()),
        scene( new QGraphicsScene()),
        gview( new QGraphicsView ()),
        stateBox( new StateBox())
    {
        QColor c (242,251,235);
        QBrush brush (c, Qt::SolidPattern);
        scene->setBackgroundBrush(brush);
        ui->setupUi(this);
        ui->horizontalLayout->addWidget( gview);
        stateBox->setPos(200,200);
        stateBox->rotate(45);
        scene->addItem( stateBox);
        gview->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
        gview->setScene(  scene);
        gview->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
        gview->show();
    }
    
    void MainWindow::resizeEvent(QResizeEvent * )
    {
    }
    
    
    MainWindow::~MainWindow()
    {
        delete gview;
        delete stateBox;
        delete scene;
        delete ui;
    }
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    #include <QMainWindow>
    #include <QGraphicsItem>
    #include <QGraphicsScene>
    #include <QGraphicsView>
    #include <QGraphicsEllipseItem>
    #include <QBrush>
    #include <QScrollBar>
    #include <QResizeEvent>
    #include "statebox.h"
    
    namespace Ui
    {
        class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui; ///< QtCreator made this instance.
        QGraphicsScene * scene ; ///< the scene will contain the graphics item 'StateBox'
        QGraphicsView * gview; ///< the graphics view will contain and display the scene.
        StateBox * stateBox; ///< this is my custom QGraphicsItem
    
        virtual void resizeEvent(QResizeEvent *);///< re-implementing this event handler of the QMainWindow class allows my to capture re-size window values - not used in this project
    };
    
    #endif // MAINWINDOW_H
    

    main.cpp

    #include <QtGui/QApplication>
    #include "mainwindow.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    pro file:

    QT       += core gui
    
    TARGET = GraphicsViewFrameWork_lesson_3
    TEMPLATE = app
    
    
    SOURCES += main.cpp\
            mainwindow.cpp \
        statebox.cpp \
        cornergrabber.cpp
    
    HEADERS  += mainwindow.h \
        statebox.h \
        cornergrabber.h
    
    FORMS    += mainwindow.ui
    
    D 1 Reply Last reply
    0
    • O ollax452

      Hi!
      I have a text-box/rectangle with corner-grabbers to enable to change width & height (draggable corners). But after a rotation/transform the re-size does not works as expected. When dragging the corners I want the oppsite corner to be stucked/not moving as it does when the text-box is not rotated. Please can some have a look at it and give me some advices.

      Best Regards
      Olle

      This function is used to rotate the textbox:

      void StateBox::rotate(qreal angle)
      {
          setTransformOriginPoint(boundingRect().center());
          setRotation(45);
      }
      
      

      textbox rotated.png

      statebox.cpp file:

      #include "statebox.h"
      
      #include <QBrush>
      #include <QLinearGradient>
      #include <QDebug>
      
      #include "math.h"
      
      StateBox::StateBox():
              _text(),
              _outterborderColor(Qt::black),
              _outterborderPen(),
              _location(0,0),
              _dragStart(0,0),
              _gridSpace(10),
              _width(250),
              _height(200),
              _cornerDragStart(0,0),
              _XcornerGrabBuffer(20),
              _YcornerGrabBuffer(20),
              _drawingWidth(  _width -   _XcornerGrabBuffer),
              _drawingHeight( _height -  _YcornerGrabBuffer),
              _drawingOrigenX( _XcornerGrabBuffer),
              _drawingOrigenY( _YcornerGrabBuffer)
      {
      
          _outterborderPen.setWidth(2);
          _outterborderPen.setColor(_outterborderColor);
      
          _text.setPos(35,35);
          _text.setPlainText("text goes here");
          _text.setParentItem(this);
      
          this->setAcceptHoverEvents(true);
      }
      
      void StateBox::adjustSize(int x, int y)
      {
          _width += x;
          _height += y;
          _drawingWidth =  _width - _XcornerGrabBuffer;
          _drawingHeight=  _height - _YcornerGrabBuffer;
      }
      
      bool StateBox::sceneEventFilter ( QGraphicsItem * watched, QEvent * event )
      {
          qDebug() << " QEvent == " + QString::number(event->type());
      
          CornerGrabber * corner = dynamic_cast<CornerGrabber *>(watched);
          if ( corner == NULL) return false; // not expected to get here
      
          QGraphicsSceneMouseEvent * mevent = dynamic_cast<QGraphicsSceneMouseEvent*>(event);
          if ( mevent == NULL)
          {
              // this is not one of the mouse events we are interrested in
              return false;
          }
      
          switch (event->type() )
          {
                  // if the mouse went down, record the x,y coords of the press, record it inside the corner object
              case QEvent::GraphicsSceneMousePress:
                  {
                      corner->setMouseState(CornerGrabber::kMouseDown);
                      corner->mouseDownX = mevent->pos().x();
                      corner->mouseDownY = mevent->pos().y();
                  }
                  break;
      
              case QEvent::GraphicsSceneMouseRelease:
                  {
                      corner->setMouseState(CornerGrabber::kMouseReleased);
      
                  }
                  break;
      
              case QEvent::GraphicsSceneMouseMove:
                  {
                      corner->setMouseState(CornerGrabber::kMouseMoving );
                  }
                  break;
      
              default:
                  // we dont care about the rest of the events
                  return false;
                  break;
          }
      
          if ( corner->getMouseState() == CornerGrabber::kMouseMoving )
          {
              qreal x = mevent->pos().x(), y = mevent->pos().y();
      
              // depending on which corner has been grabbed, we want to move the position
              // of the item as it grows/shrinks accordingly. so we need to eitehr add
              // or subtract the offsets based on which corner this is.
      
              int XaxisSign = 0;
              int YaxisSign = 0;
              switch( corner->getCorner() )
              {
              case 0:
                  {
                      XaxisSign = +1;
                      YaxisSign = +1;
                  }
                  break;
      
              case 1:
                  {
                      XaxisSign = -1;
                      YaxisSign = +1;
                  }
                  break;
      
              case 2:
                  {
                      XaxisSign = -1;
                      YaxisSign = -1;
                  }
                  break;
      
              case 3:
                  {
                      XaxisSign = +1;
                      YaxisSign = -1;
                  }
                  break;
      
              }
      
              // if the mouse is being dragged, calculate a new size and also re-position
              // the box to give the appearance of dragging the corner out/in to resize the box
      
              int xMoved = corner->mouseDownX - x;
              int yMoved = corner->mouseDownY - y;
      
              int newWidth = _width + ( XaxisSign * xMoved);
              if ( newWidth < 40 ) newWidth  = 40;
      
              int newHeight = _height + (YaxisSign * yMoved) ;
              if ( newHeight < 40 ) newHeight = 40;
      
              int deltaWidth  =   newWidth - _width ;
              int deltaHeight =   newHeight - _height ;
      
              adjustSize(  deltaWidth ,   deltaHeight);
      
              deltaWidth *= (-1);
              deltaHeight *= (-1);
      
              if ( corner->getCorner() == 0 )
              {
                  int newXpos = this->pos().x() + deltaWidth;
                  int newYpos = this->pos().y() + deltaHeight;
                  this->setPos(newXpos, newYpos);
              }
              else   if ( corner->getCorner() == 1 )
              {
                  int newYpos = this->pos().y() + deltaHeight;
                  this->setPos(this->pos().x(), newYpos);
              }
              else   if ( corner->getCorner() == 3 )
              {
                  int newXpos = this->pos().x() + deltaWidth;
                  this->setPos(newXpos,this->pos().y());
              }
      
              setCornerPositions();
      
              this->update();
          }
      
          return true;// true => do not send event to watched - we are finished with this event
      }
      
      // for supporting moving the box across the scene
      void StateBox::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
      {
          event->setAccepted(true);
          _location.setX( ( static_cast<int>(_location.x()) / _gridSpace) * _gridSpace );
          _location.setY( ( static_cast<int>(_location.y()) / _gridSpace) * _gridSpace );
          this->setPos(_location);
      }
      
      
      // for supporting moving the box across the scene
      void StateBox::mousePressEvent ( QGraphicsSceneMouseEvent * event )
      {
          event->setAccepted(true);
          _dragStart = event->pos();
      }
      
      
      // for supporting moving the box across the scene
      void StateBox::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
      {
          QPointF newPos = event->pos() ;
          _location += (newPos - _dragStart);
          this->setPos(_location);
      }
      
      // remove the corner grabbers
      void StateBox::hoverLeaveEvent ( QGraphicsSceneHoverEvent * )
      {
          _outterborderColor = Qt::black;
      
          _corners[0]->setParentItem(NULL);
          _corners[1]->setParentItem(NULL);
          _corners[2]->setParentItem(NULL);
          _corners[3]->setParentItem(NULL);
      
          delete _corners[0];
          delete _corners[1];
          delete _corners[2];
          delete _corners[3];
      }
      
      // create the corner grabbers
      void StateBox::hoverEnterEvent ( QGraphicsSceneHoverEvent * )
      {
          _outterborderColor = Qt::red;
      
          _corners[0] = new CornerGrabber(this,0);
          _corners[1] = new CornerGrabber(this,1);
          _corners[2] = new CornerGrabber(this,2);
          _corners[3] = new CornerGrabber(this,3);
      
      
          _corners[0]->installSceneEventFilter(this);
          _corners[1]->installSceneEventFilter(this);
          _corners[2]->installSceneEventFilter(this);
          _corners[3]->installSceneEventFilter(this);
      
          setCornerPositions();
      
      }
      
      void StateBox::setCornerPositions()
      {
          _corners[0]->setPos(_drawingOrigenX, _drawingOrigenY);
          _corners[1]->setPos(_drawingWidth,  _drawingOrigenY);
          _corners[2]->setPos(_drawingWidth , _drawingHeight);
          _corners[3]->setPos(_drawingOrigenX, _drawingHeight);
      }
      
      QRectF StateBox::boundingRect() const
      {
          return QRectF(0,0,_width,_height);
      }
      
      void StateBox::paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
      {
          int shadowThickness = 3;
      
          QLinearGradient gradient;
          gradient.setStart(_drawingOrigenX,_drawingOrigenY);
          gradient.setFinalStop( _drawingWidth ,_drawingOrigenY);
          QColor grey1(150,150,150,125);// starting color of the gradient - can play with the starting color and ,point since its not visible anyway
      
          // grey2 is ending color of the gradient - this is what will show up as the shadow. the last parameter is the alpha blend, its set
          // to 125 allowing a mix of th color and and the background, making more realistic shadow effect.
          QColor grey2(225,225,225,125);
      
      
          gradient.setColorAt((qreal)0, grey1 );
          gradient.setColorAt((qreal)1, grey2 );
      
          QBrush brush(gradient);
      
          painter->setBrush( brush);
      
          // for the desired effect, no border will be drawn, and because a brush was set, the drawRoundRect will fill the box with the gradient brush.
          _outterborderPen.setStyle(Qt::NoPen);
          painter->setPen(_outterborderPen);
      
          QPointF topLeft (_drawingOrigenX,_drawingOrigenX);
          QPointF bottomRight ( _drawingWidth , _drawingHeight);
      
          QRectF rect (topLeft, bottomRight);
      
          painter->drawRoundRect(rect,25,25); // corner radius of 25 pixels
      
          // draw the top box, the visible one
          QBrush brush2(QColor(243,255,216,255),Qt::SolidPattern);
      
          painter->setBrush( brush2);
      
          QPointF topLeft2 (_drawingOrigenX, _drawingOrigenY);
          QPointF bottomRight2 ( _drawingWidth-shadowThickness, _drawingHeight-shadowThickness);
      
          QRectF rect2 (topLeft2, bottomRight2);
      
          painter->drawRoundRect(rect2,25,25);
      
      }
      
      void StateBox::mouseMoveEvent(QGraphicsSceneDragDropEvent *event)
      {
          event->setAccepted(false);
      }
      
      void StateBox::mousePressEvent(QGraphicsSceneDragDropEvent *event)
      {
          event->setAccepted(false);
      }
      
      void StateBox::rotate(qreal angle)
      {
          setTransformOriginPoint(boundingRect().center());
          setRotation(45);
      }
      

      statebox.h

      #ifndef STATEBOX_H
      #define STATEBOX_H
      
      #include <QGraphicsItem>
      #include <QGraphicsRectItem>
      #include <QGraphicsTextItem>
      #include <QGraphicsSceneHoverEvent>
      #include <QGraphicsSceneMouseEvent>
      #include <QColor>
      #include <QPainter>
      #include <QPen>
      #include <QPointF>
      #include "cornergrabber.h"
      
      class StateBox : public QGraphicsItem
      {
      public:
          StateBox();
          QGraphicsTextItem _text;    ///< sample text to go in the title area.
      
          void setGridSpace(int space);
          void rotate(qreal angle);
      
          private:
      
      
          virtual QRectF boundingRect() const; ///< must be re-implemented in this class to provide the diminsions of the box to the QGraphicsView
          virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ///< must be re-implemented here to pain the box on the paint-event
          virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover enter events
          virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover leave events
      
          virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );///< allows the main object to be moved in the scene by capturing the mouse move events
          virtual void mousePressEvent (QGraphicsSceneMouseEvent * event );
          virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event );
      
          virtual void mouseMoveEvent(QGraphicsSceneDragDropEvent *event);
          virtual void mousePressEvent(QGraphicsSceneDragDropEvent *event);
          virtual bool sceneEventFilter ( QGraphicsItem * watched, QEvent * event ) ;
      
          void setCornerPositions();
          void adjustSize(int x, int y);
      
      
          QColor _outterborderColor; ///< the hover event handlers will toggle this between red and black
          QPen _outterborderPen; ///< the pen is used to paint the red/black border
          QPointF _location;
          QPointF _dragStart;
          int     _gridSpace;
          qreal   _width;
          qreal   _height;
      
          QPointF _cornerDragStart;
      
          int _XcornerGrabBuffer;
          int _YcornerGrabBuffer;
          qreal   _drawingWidth;
          qreal   _drawingHeight;
          qreal   _drawingOrigenX;
          qreal   _drawingOrigenY;
      
          CornerGrabber*  _corners[4];// 0,1,2,3  - starting at x=0,y=0 and moving clockwise around the box
      };
      
      #endif // STATEBOX_H
      

      cornergrabber.cpp

      #include "cornergrabber.h"
      
      CornerGrabber::CornerGrabber(QGraphicsItem *parent,  int corner) :
          QGraphicsItem(parent),
          mouseDownX(0),
          mouseDownY(0),
          _outterborderColor(Qt::black),
          _outterborderPen(),
          _width(6),
          _height(6),
          _corner(corner),
          _mouseButtonState(kMouseReleased)
      {
          setParentItem(parent);
      
          _outterborderPen.setWidth(2);
          _outterborderPen.setColor(_outterborderColor);
      
         this->setAcceptHoverEvents(true);
      }
      
      void CornerGrabber::setMouseState(int s)
      {
          _mouseButtonState = s;
      }
      
      int CornerGrabber::getMouseState()
      {
          return _mouseButtonState;
      }
      
      int CornerGrabber::getCorner()
      {
          return _corner;
      }
      
      void CornerGrabber::mouseMoveEvent(QGraphicsSceneDragDropEvent *event)
      {
          event->setAccepted(false);
      }
      
      void CornerGrabber::mousePressEvent(QGraphicsSceneDragDropEvent *event)
      {
          event->setAccepted(false);
      }
      
      void CornerGrabber::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
      {
          event->setAccepted(true);
      }
      
      void CornerGrabber::mousePressEvent ( QGraphicsSceneMouseEvent * event )
      {
          event->setAccepted(false);
      }
      
      void CornerGrabber::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
      {
          event->setAccepted(false);
      }
      
      void CornerGrabber::hoverLeaveEvent ( QGraphicsSceneHoverEvent * )
      {
          _outterborderColor = Qt::black;
          this->update(0,0,_width,_height);
      }
      
      void CornerGrabber::hoverEnterEvent ( QGraphicsSceneHoverEvent * )
      {
          _outterborderColor = Qt::red;
          this->update(0,0,_width,_height);
      }
      
      QRectF CornerGrabber::boundingRect() const
      {
          return QRectF(0,0,_width,_height);
      }
      
      void CornerGrabber::paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
      {
          _outterborderPen.setCapStyle(Qt::SquareCap);
          _outterborderPen.setStyle(Qt::SolidLine);
          painter->setPen(_outterborderPen);
      
          QPointF topLeft (0, 0);
          QPointF bottomRight ( _width, _height);
      
          QRectF rect (topLeft, bottomRight);
      
          QBrush brush (Qt::SolidPattern);
          brush.setColor (_outterborderColor);
          painter->fillRect(rect,brush);
      
      }
      
      

      cornergrabber.h

      #ifndef CORNERGRABBER_H
      #define CORNERGRABBER_H
      
      #include <QObject>
      #include <QGraphicsItem>
      #include <QGraphicsRectItem>
      #include <QGraphicsTextItem>
      #include <QGraphicsSceneHoverEvent>
      #include <QGraphicsSceneMouseEvent>
      #include <QColor>
      #include <QPainter>
      #include <QPen>
      #include <QPointF>
      
      class CornerGrabber : public QGraphicsItem
      {
      
      public:
          explicit CornerGrabber(QGraphicsItem *parent = 0,  int corner=0);
      
          int  getCorner(); ///< allows the owner to find out which coner this is
          void setMouseState(int); ///< allows the owner to record the current mouse state
          int  getMouseState(); ///< allows the owner to get the current mouse state
      
          qreal mouseDownX;
          qreal mouseDownY;
      
           enum {kMouseReleased=0, kMouseDown, kMouseMoving}; ///< define the mouse states
      
      private:
      
          virtual QRectF boundingRect() const; ///< must be re-implemented in this class to provide the diminsions of the box to the QGraphicsView
          virtual void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); ///< must be re-implemented here to pain the box on the paint-event
          virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover enter events
          virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); ///< must be re-implemented to handle mouse hover leave events
          virtual void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
          virtual void mouseMoveEvent(QGraphicsSceneDragDropEvent *event);
          virtual void mousePressEvent (QGraphicsSceneMouseEvent * event );
          virtual void mousePressEvent(QGraphicsSceneDragDropEvent *event);
          virtual void mouseReleaseEvent (QGraphicsSceneMouseEvent * event );
      
          QColor _outterborderColor; ///< the hover event handlers will toggle this between red and black
          QPen _outterborderPen; ///< the pen is used to paint the red/black border
      
          qreal   _width;
          qreal   _height;
      
          int _corner;// 0,1,2,3  - starting at x=0,y=0 and moving clockwise around the box
          int _mouseButtonState;
      };
      
      #endif // CORNERGRABBER_H
      

      mainwindow.cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      #include <QDebug>
      #include <QSizePolicy>
      #include <QGraphicsLineItem>
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow()),
          scene( new QGraphicsScene()),
          gview( new QGraphicsView ()),
          stateBox( new StateBox())
      {
          QColor c (242,251,235);
          QBrush brush (c, Qt::SolidPattern);
          scene->setBackgroundBrush(brush);
          ui->setupUi(this);
          ui->horizontalLayout->addWidget( gview);
          stateBox->setPos(200,200);
          stateBox->rotate(45);
          scene->addItem( stateBox);
          gview->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
          gview->setScene(  scene);
          gview->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
          gview->show();
      }
      
      void MainWindow::resizeEvent(QResizeEvent * )
      {
      }
      
      
      MainWindow::~MainWindow()
      {
          delete gview;
          delete stateBox;
          delete scene;
          delete ui;
      }
      

      mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      #include <QMainWindow>
      #include <QGraphicsItem>
      #include <QGraphicsScene>
      #include <QGraphicsView>
      #include <QGraphicsEllipseItem>
      #include <QBrush>
      #include <QScrollBar>
      #include <QResizeEvent>
      #include "statebox.h"
      
      namespace Ui
      {
          class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui; ///< QtCreator made this instance.
          QGraphicsScene * scene ; ///< the scene will contain the graphics item 'StateBox'
          QGraphicsView * gview; ///< the graphics view will contain and display the scene.
          StateBox * stateBox; ///< this is my custom QGraphicsItem
      
          virtual void resizeEvent(QResizeEvent *);///< re-implementing this event handler of the QMainWindow class allows my to capture re-size window values - not used in this project
      };
      
      #endif // MAINWINDOW_H
      

      main.cpp

      #include <QtGui/QApplication>
      #include "mainwindow.h"
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          MainWindow w;
          w.show();
      
          return a.exec();
      }
      

      pro file:

      QT       += core gui
      
      TARGET = GraphicsViewFrameWork_lesson_3
      TEMPLATE = app
      
      
      SOURCES += main.cpp\
              mainwindow.cpp \
          statebox.cpp \
          cornergrabber.cpp
      
      HEADERS  += mainwindow.h \
          statebox.h \
          cornergrabber.h
      
      FORMS    += mainwindow.ui
      
      D Offline
      D Offline
      DavidFaure
      wrote on last edited by
      #2

      @ollax452 To fix this, the idea is to make sure the old center of rotation remains in place. I did that with code like

      // How much did the old center of rotation move because of the change of center of rotation?
      // Move back by that much, so it stays where it used to be
      const auto oldCenterInNewItemCoords = oldBoundingBox.center() - newBoundingBox.center();
      QTransform rotationTransform;
      rotationTransform.rotate(rotation());
      const auto newPosOfOldCenter = rotationTransform.map(oldCenterInNewItemCoords);
      const auto unwantedMovement  = newPosOfOldCenter - oldCenterInNewItemCoords;
      newBoundingBox.translate(-unwantedMovement);
      

      (this could obviously be simplified by merging some lines, but I find it more readable this way)

      And of course you need to call setTransformOriginPoint(boundingRect().center()); when the bounding rect changes (so, not in rotate(), but rather in setGeometry() or whichever method changes the variables used by boundingRect)

      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 Extensions
      • Unsolved