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. How to rotate QGraphicsItem right after mouse?
Forum Updated to NodeBB v4.3 + New Features

How to rotate QGraphicsItem right after mouse?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 4 Posters 654 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.
  • ValdermanV Offline
    ValdermanV Offline
    Valderman
    wrote on last edited by
    #1

    Hello!
    My application have QGraphicsScene and custom QGraphicsItem on it.
    I wrote the following code for my custom graphics item rotation:

    // FigureScene is inherited from QGraphicsScene
    void FigureScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
    {
    	// Remember last press coordinate
    	if (mouseEvent->button() == Qt::RightButton)
    	{
            	lastRightMousePressed = mouseEvent->screenPos();
    	}
    }
    
    void FigureScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
    {
    	if (mouseEvent->button() == Qt::RightButton)
    	{
    		const auto sceneCoord = mouseEvent->scenePos();
    
    		foreach (QGraphicsItem* item, m_parentScene->selectedItems())
            	{
    			QTransform transform;
    			QPointF	   center = item->sceneBoundingRect().center();
            	
    			transform.translate(center.x(), center.y());
            	
     			qreal angle
                                  = qAtan2(lastRightMousePressed.y() - sceneCoord.y(),
                                           lastRightMousePressed.x() - sceneCoord.x());
            	
    			transform.rotate(angle);
    			transform.translate(-center.x(), -center.y());
            	
    			item->setPos(transform.map(item->pos()));
    			item->setRotation(item->rotation() + angle);
            	}
    	}
    }
    

    And my figure rotating something like this:
    figure-rotation-problem.gif
    The problem is that when I rotate the mouse clockwise or counterclockwise, the figure rotates only counterclockwise.

    I would like my figure to rotate right after the mouse.
    How can I achieve that?

    SGaistS 1 Reply Last reply
    0
    • ValdermanV Valderman

      Hello!
      My application have QGraphicsScene and custom QGraphicsItem on it.
      I wrote the following code for my custom graphics item rotation:

      // FigureScene is inherited from QGraphicsScene
      void FigureScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
      {
      	// Remember last press coordinate
      	if (mouseEvent->button() == Qt::RightButton)
      	{
              	lastRightMousePressed = mouseEvent->screenPos();
      	}
      }
      
      void FigureScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
      {
      	if (mouseEvent->button() == Qt::RightButton)
      	{
      		const auto sceneCoord = mouseEvent->scenePos();
      
      		foreach (QGraphicsItem* item, m_parentScene->selectedItems())
              	{
      			QTransform transform;
      			QPointF	   center = item->sceneBoundingRect().center();
              	
      			transform.translate(center.x(), center.y());
              	
       			qreal angle
                                    = qAtan2(lastRightMousePressed.y() - sceneCoord.y(),
                                             lastRightMousePressed.x() - sceneCoord.x());
              	
      			transform.rotate(angle);
      			transform.translate(-center.x(), -center.y());
              	
      			item->setPos(transform.map(item->pos()));
      			item->setRotation(item->rotation() + angle);
              	}
      	}
      }
      

      And my figure rotating something like this:
      figure-rotation-problem.gif
      The problem is that when I rotate the mouse clockwise or counterclockwise, the figure rotates only counterclockwise.

      I would like my figure to rotate right after the mouse.
      How can I achieve that?

      SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      You need to keep track of the last position of the mouse so your can determine in which direction it's going and adjust the rotation direction accordingly.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Instead of doing additive rotation each move I would modify item's origin and remember its rotation on press in a map and then just set rotation on move. This would make the item follow cursor with pixel accuracy.

        In press:

        itemRotations.clear(); // this is a QMap<QGraphicsItem*, qreal>
        const QPointF mousePos = mouseEvent->scenePos();
        
        foreach (QGraphicsItem* item, selectedItems())
        {
            const QPointF itemOrigin = item->sceneBoundingRect().center();
            const qreal angle = qAtan2(mousePos.y() - itemOrigin.y(),
                                       mousePos.x() - itemOrigin.x());
        
            item->setTransformOriginPoint(itemOrigin);
            itemRotations[item] = item->rotation() - qRadiansToDegrees(angle);
        }
        

        and in move:

        const QPointF mousePos = mouseEvent->scenePos();
        
        foreach (QGraphicsItem* item, selectedItems())
        {
            const QPointF itemOrigin = item->transformOriginPoint();
            const qreal angle = qAtan2(mousePos.y() - itemOrigin.y(),
                                       mousePos.x() - itemOrigin.x());
        
            item->setRotation(itemRotations[item] + qRadiansToDegrees(angle));
        }
        
        ValdermanV 1 Reply Last reply
        2
        • Chris KawaC Chris Kawa

          Instead of doing additive rotation each move I would modify item's origin and remember its rotation on press in a map and then just set rotation on move. This would make the item follow cursor with pixel accuracy.

          In press:

          itemRotations.clear(); // this is a QMap<QGraphicsItem*, qreal>
          const QPointF mousePos = mouseEvent->scenePos();
          
          foreach (QGraphicsItem* item, selectedItems())
          {
              const QPointF itemOrigin = item->sceneBoundingRect().center();
              const qreal angle = qAtan2(mousePos.y() - itemOrigin.y(),
                                         mousePos.x() - itemOrigin.x());
          
              item->setTransformOriginPoint(itemOrigin);
              itemRotations[item] = item->rotation() - qRadiansToDegrees(angle);
          }
          

          and in move:

          const QPointF mousePos = mouseEvent->scenePos();
          
          foreach (QGraphicsItem* item, selectedItems())
          {
              const QPointF itemOrigin = item->transformOriginPoint();
              const qreal angle = qAtan2(mousePos.y() - itemOrigin.y(),
                                         mousePos.x() - itemOrigin.x());
          
              item->setRotation(itemRotations[item] + qRadiansToDegrees(angle));
          }
          
          ValdermanV Offline
          ValdermanV Offline
          Valderman
          wrote on last edited by Valderman
          #4

          @Chris-Kawa, Hello and thank you so much for your answer!
          But I don't get it. Here is code that you propose:

          void FigureScene::onRightMousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
          {
          	itemRotations.clear();
          	const QPointF mousePos = mouseEvent->scenePos();
          
          	foreach (QGraphicsItem* item, selectedItems())
          	{
          		const QPointF itemOrigin = item->sceneBoundingRect().center();
          		const qreal angle 
                              = qAtan2(mousePos.y() - itemOrigin.y(), mousePos.x() - itemOrigin.x());
          
          		item->setTransformOriginPoint(itemOrigin);
          		itemRotations[item] = item->rotation() - qRadiansToDegrees(angle);
          	}
          }
          
          void FigureScene::onRightMouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
          {
          	const QPointF mousePos = mouseEvent->scenePos();
          
          	foreach (QGraphicsItem* item, selectedItems())
          	{
          		const QPointF itemOrigin = item->transformOriginPoint();
          		const qreal angle
                                = qAtan2(mousePos.y() - itemOrigin.y(),  mousePos.x() - itemOrigin.x());
          
          		item->setRotation(itemRotations[item] + qRadiansToDegrees(angle));
          	}
          }
          

          Here is what happens:
          figure-rotation-problem-2.gif

          Figure just running away right after movement.
          Is it something wrong with setting position?

          johngodJ 1 Reply Last reply
          0
          • ValdermanV Valderman

            @Chris-Kawa, Hello and thank you so much for your answer!
            But I don't get it. Here is code that you propose:

            void FigureScene::onRightMousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
            {
            	itemRotations.clear();
            	const QPointF mousePos = mouseEvent->scenePos();
            
            	foreach (QGraphicsItem* item, selectedItems())
            	{
            		const QPointF itemOrigin = item->sceneBoundingRect().center();
            		const qreal angle 
                                = qAtan2(mousePos.y() - itemOrigin.y(), mousePos.x() - itemOrigin.x());
            
            		item->setTransformOriginPoint(itemOrigin);
            		itemRotations[item] = item->rotation() - qRadiansToDegrees(angle);
            	}
            }
            
            void FigureScene::onRightMouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
            {
            	const QPointF mousePos = mouseEvent->scenePos();
            
            	foreach (QGraphicsItem* item, selectedItems())
            	{
            		const QPointF itemOrigin = item->transformOriginPoint();
            		const qreal angle
                                  = qAtan2(mousePos.y() - itemOrigin.y(),  mousePos.x() - itemOrigin.x());
            
            		item->setRotation(itemRotations[item] + qRadiansToDegrees(angle));
            	}
            }
            

            Here is what happens:
            figure-rotation-problem-2.gif

            Figure just running away right after movement.
            Is it something wrong with setting position?

            johngodJ Offline
            johngodJ Offline
            johngod
            wrote on last edited by
            #5

            @Valderman

            I did something like that in a project of mine, but with a difference that the rectangle does not rotate in his center but rotates relative to a center defined in a first click position called commandInitialPos, then you do a second click to start rotating, then you move the mouse to rotate.
            I am posting the relevant code I used may it can be helpfull for you to adapt

            the relevant pseudo code and link to the project:
            https://bitbucket.org/joaodeusmorgado/techdrawstudio/src/142960ab5c809ddcbd20fb40f294e01d85c850d5/qml/qmlEntities/EntityTemplate.qml#lines-117

            //first click - define the center of rotation
            onCommandCprStart: function(pos) {
                commandInitialPos = pos //assume that pos is the mouse click position
            }
            

            https://bitbucket.org/joaodeusmorgado/techdrawstudio/src/142960ab5c809ddcbd20fb40f294e01d85c850d5/qml/qmlEntities/RectangleThick.qml#lines-39

            //second click - start rotation position
            onCommandCprUpdate: function(pos, ....){
                rotateStartPoint = pos //save the start rotation position
            	//calculates and saves the start angle
            	rotateStartAngle = mathLib.angleFromPoints(commandInitialPos, rotateStartPoint) 
            	rectP0aux = re.p0 // here I just saving the rectangle initiall position vertexs
            	rectP1aux = re.p1
            	rectP2aux = re.p2
            	rectP3aux = re.p3
            }
            

            https://bitbucket.org/joaodeusmorgado/techdrawstudio/src/142960ab5c809ddcbd20fb40f294e01d85c850d5/qml/qmlEntities/RectangleThick.qml#lines-75

            onCommandMtm: function(pos, ....){//this is equivalent to mouse move 
            	rotateUpdateAngle = mathLib.angleFromPoints(commandInitialPos, pos)
            
            	var angle = rotateUpdateAngle - rotateStartAngle
                // lets do it baby, lets rotate it, yeahhhh, updates the rectangles vertices, which is the rotation
            	re.p0 = mathLib.rotate2DFromPoint(commandInitialPos, angle, rectP0aux)
            	re.p1 = mathLib.rotate2DFromPoint(commandInitialPos, angle, rectP1aux)
            	re.p2 = mathLib.rotate2DFromPoint(commandInitialPos, angle, rectP2aux)
            	re.p3 = mathLib.rotate2DFromPoint(commandInitialPos, angle, rectP3aux)
            }
            

            https://bitbucket.org/joaodeusmorgado/techdrawstudio/src/142960ab5c809ddcbd20fb40f294e01d85c850d5/mathlib.cpp#lines-103

            QVector3D MathLib::rotate2DFromPoint(const QVector3D &center, const float &angle, const QVector3D &p) const
            {
                float cosAngle = qCos(angle);
                float sinAngle = qSin(angle);
                float x = cosAngle*p.x() - sinAngle*p.y() + center.x() - cosAngle*center.x() + sinAngle*center.y();
                float y = sinAngle*p.x() + cosAngle*p.y() + center.y() - sinAngle*center.x() - cosAngle*center.y();
                return QVector3D(x, y, p.z());
            }
            

            This is the rectangle rotating:
            alt text

            1 Reply Last reply
            0
            • ValdermanV Valderman has marked this topic as solved on

            • Login

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