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?
Qt 6.11 is out! See what's new in the release blog

How to rotate QGraphicsItem right after mouse?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 4 Posters 999 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