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. QGraphicsRectItem item translation instead of movement?

QGraphicsRectItem item translation instead of movement?

Scheduled Pinned Locked Moved Solved General and Desktop
qt c++qgraphicssceneqtransformqgraphicsitem
12 Posts 3 Posters 968 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.
  • S StudentScripter
    17 Aug 2024, 17:08

    Or how to do it best practice? If all should be done by matrix transformations?

    J Offline
    J Offline
    JonB
    wrote on 17 Aug 2024, 17:36 last edited by JonB
    #3

    @StudentScripter
    You can manipulate the transform matrix values directly or use the convenience methods rotate() etc. in it or call QGraphicsRectItem::setRotation() etc. methods. Read Transformations..

    You create a separate QTransform for the translate() and then combine that with current transform via currentTransform * translation. You could do currentTransform.translate(); setTransform(currentTransform); directly.

    S 1 Reply Last reply 27 Aug 2024, 15:04
    0
    • J JonB
      17 Aug 2024, 17:36

      @StudentScripter
      You can manipulate the transform matrix values directly or use the convenience methods rotate() etc. in it or call QGraphicsRectItem::setRotation() etc. methods. Read Transformations..

      You create a separate QTransform for the translate() and then combine that with current transform via currentTransform * translation. You could do currentTransform.translate(); setTransform(currentTransform); directly.

      S Offline
      S Offline
      StudentScripter
      wrote on 27 Aug 2024, 15:04 last edited by
      #4

      @JonB Thats good, one problem i have with my code using the translation for movement in the scene makes the movement of the object sluggish.

      When i drag the graphicsitem normaly with the default method it is smooth and follows the mouse drag 1:1.
      But when i try to use translation instead (cause normal moving an rotating messes up the rotation and scaling) it is sluggish and lack behind the mouse when moving fast.

      Any idea how to fix? I can't be the first person who wants to implement a moveable, resizable and rotatable graphicsitem with handles.

      Thanks alot for helping me out. :D

      J 1 Reply Last reply 27 Aug 2024, 15:38
      0
      • S StudentScripter
        27 Aug 2024, 15:04

        @JonB Thats good, one problem i have with my code using the translation for movement in the scene makes the movement of the object sluggish.

        When i drag the graphicsitem normaly with the default method it is smooth and follows the mouse drag 1:1.
        But when i try to use translation instead (cause normal moving an rotating messes up the rotation and scaling) it is sluggish and lack behind the mouse when moving fast.

        Any idea how to fix? I can't be the first person who wants to implement a moveable, resizable and rotatable graphicsitem with handles.

        Thanks alot for helping me out. :D

        J Offline
        J Offline
        JonB
        wrote on 27 Aug 2024, 15:38 last edited by
        #5

        @StudentScripter
        If it doesn't keep up with fast moving mouse/drag you may want to buffer up some movements, by time. E.g. perhaps once start dragging accumulate moves for say 10th second and then do a single move for multiple little ones.

        S 1 Reply Last reply 27 Aug 2024, 17:32
        1
        • J JonB
          27 Aug 2024, 15:38

          @StudentScripter
          If it doesn't keep up with fast moving mouse/drag you may want to buffer up some movements, by time. E.g. perhaps once start dragging accumulate moves for say 10th second and then do a single move for multiple little ones.

          S Offline
          S Offline
          StudentScripter
          wrote on 27 Aug 2024, 17:32 last edited by
          #6

          @JonB Thanks alot man. Seems to be working, but is having a timer running everytime the item starts to move a good idea? I always thought having a timer inside qgraphicsitem is pretty poor, but maybe im wrong.

          Here is an example of my implementation:

          ResizablePixmapItem::ResizablePixmapItem(const QPixmap &pixmap, QGraphicsItem *parent)
              : QGraphicsRectItem{parent}, m_pixmap(pixmap)
          {
              setRect(0,0,100,100);
              setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsRectItem::ItemSendsScenePositionChanges);
          
          
          
          
               MoveTimer = new QTimer(this);
               connect(MoveTimer, &QTimer::timeout, this, &ResizablePixmapItem::applyBufferedMovement);
          }
          
          
          
          
          void ResizablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
          {
          
              MoveTimer->start(15);
          
          
              QGraphicsRectItem::mousePressEvent(event);
          }
          
          void ResizablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
          {
              if(isSelected() && !handles.empty() && !areHandlesSelected()){
                  UpdateHandles();
              }
          
              // Accumulate the movement delta
              QPointF delta = event->scenePos() - event->lastScenePos();
              accumulatedDelta += delta;
          
              event->accept();
          }
          
          void ResizablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
          {
              MoveTimer->stop();
              QGraphicsRectItem::mouseReleaseEvent(event);
          }
          
          
          
          
          void ResizablePixmapItem::applyBufferedMovement()
          {
              if (!accumulatedDelta.isNull()) {
                  prepareGeometryChange();
          
                  QTransform currentTransform = this->transform();
                  QTransform translation;
                  translation.translate(accumulatedDelta.x(), accumulatedDelta.y());
          
                  setTransform(currentTransform * translation);
          
                  qreal translationX = transform().m31();  // Translation along the X axis
                  qreal translationY = transform().m32();  // Translation along the Y axis
                  qDebug() << "Buffered Translation X:" << translationX << "Translation Y:" << translationY;
          
                  scene()->update(); // Update the scene to reflect the movement
          
                  // Reset the accumulated delta after applying the transformation
                  accumulatedDelta = QPointF(0, 0);
              }
          }
          
          1 Reply Last reply
          0
          • S StudentScripter has marked this topic as solved on 27 Aug 2024, 17:32
          • S StudentScripter
            14 Aug 2024, 16:09

            I want to do resizing, moving, rotation all as transforms, but is the way i implemented it good, or is there a better solution?

            void resizablepixmapitem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
            {
                prepareGeometryChange();
            
                QPointF delta = event->scenePos() - event->lastScenePos();
            
                QTransform currentTransform = this->transform();
            
                QTransform translation;
                translation.translate(delta.x(), delta.y());
            
                setTransform(currentTransform * translation);
            
                qreal translationX = transform().m31();  // Translation entlang der X-Achse
                qreal translationY = transform().m32();  // Translation entlang der Y-Achse
                qDebug() << "Translation X:" << translationX << "Translation Y:" << translationY;
            
                scene()->update();
            
                //QGraphicsRectItem::mouseMoveEvent(event);
            }
            
            Pl45m4P Online
            Pl45m4P Online
            Pl45m4
            wrote on 27 Aug 2024, 22:32 last edited by Pl45m4
            #7

            @StudentScripter said in QGraphicsRectItem item translation instead of movement?:

            I want to do resizing, moving, rotation all as transforms

            I fail to understand the idea of "moving" an item using transformations, when ItemIsMovable is set...
            Few pixels left and right, top and down, ok granted, but I don't think QTranformation is intended to be used in the way you do.

            First sentence of Tranformations states:

            QGraphicsItem supports projective transformations in addition to its base position, pos().

            What you are trying to do, as I understand, is to keep the item at its "base" position and transform it to wherever, in whatever pose, scale, etc.
            This is at least what your mouseMoveEvent code does (if I'm not mistaken).

            As setting the movable flag will in addition change the items "base" position... and this might collide with the transformation stuff you are doing... and maybe that's the cause for the misbehavior you describe.

            I'm not sure about that, but I don't think you should "tranform" your item across the scene, rather than actually moving it via setPos()... or just handle the rotation and scaling, when needed and don't mind the position, as the base implementation triggered by ItemIsMovable will take care of it and find the new position for the item (where it was released and mouse movement stopped).


            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            1 Reply Last reply
            2
            • J Offline
              J Offline
              JonB
              wrote on 28 Aug 2024, 07:41 last edited by
              #8

              @StudentScripter
              I agree with @Pl45m4. I don't really know what/why you are doing "translation" when you have setPos(), ItemIsMovable or why you have to do your own work for this. Admittedly I have not written my own stuff for "draggable handles" and with rotation. You say, I think, it "goes wrong", but I don't know why: we think you don't need "translation", can you get rid of that part of your "transformation" and see how it goes?

              1 Reply Last reply
              0
              • S Offline
                S Offline
                StudentScripter
                wrote on 28 Aug 2024, 09:16 last edited by StudentScripter
                #9

                @JonB @Pl45m4 Let me explain the problem is the following:

                1. I want to apply all transformations e.g. scaling, rotation, translation/moving to my qgraphicsrectitem via a handle class,
                  --> as i understood it, if you work with these various types of transformations a proper transformation matrix is needed cause moving and scaling should always be happening before rotating

                2. My before prototype was NOT using proper transformation matrix but setPos()/ItemisMovable instead of translate, rect().setTop, setBottom andsoforth instead of scale transformation, and setRotation --> here i hit the wall where i figured a proper matrix may be need as you can see after scaling the rotation is fucked up and vice verca
                  GraphicsItem Transformation.gif

                (The yellow dot represents the center of the parent/frog image - just for visualizing purpose)

                Can't post the code cause it's getting flagged as spam. Can any moderator change this please?
                Meanwhile here is a pastebin link to the code: https://pastebin.com/kMDQUtcM

                J 1 Reply Last reply 28 Aug 2024, 09:54
                0
                • S StudentScripter
                  28 Aug 2024, 09:16

                  @JonB @Pl45m4 Let me explain the problem is the following:

                  1. I want to apply all transformations e.g. scaling, rotation, translation/moving to my qgraphicsrectitem via a handle class,
                    --> as i understood it, if you work with these various types of transformations a proper transformation matrix is needed cause moving and scaling should always be happening before rotating

                  2. My before prototype was NOT using proper transformation matrix but setPos()/ItemisMovable instead of translate, rect().setTop, setBottom andsoforth instead of scale transformation, and setRotation --> here i hit the wall where i figured a proper matrix may be need as you can see after scaling the rotation is fucked up and vice verca
                    GraphicsItem Transformation.gif

                  (The yellow dot represents the center of the parent/frog image - just for visualizing purpose)

                  Can't post the code cause it's getting flagged as spam. Can any moderator change this please?
                  Meanwhile here is a pastebin link to the code: https://pastebin.com/kMDQUtcM

                  J Offline
                  J Offline
                  JonB
                  wrote on 28 Aug 2024, 09:54 last edited by
                  #10

                  @StudentScripter
                  I really don't know, I/you would need to play with this graphics item stuff to discover what does/does not work. I believe I read that "rotation goes wrong/unexpected when using scaling at the same time", but that is all I know. I believe there is a further complication that there are two ways to achieve rotation, either via QTransform::rotate() or via QGraphicsItem::setRotation(). I am unsure whether these are identical. I think there is a difference. Be sure to read https://doc.qt.io/qt-6/qgraphicsitem.html#transformations, including where it lists "QGraphicsItem always applies the properties in a fixed, defined order".

                  S 1 Reply Last reply 28 Aug 2024, 13:21
                  0
                  • J JonB
                    28 Aug 2024, 09:54

                    @StudentScripter
                    I really don't know, I/you would need to play with this graphics item stuff to discover what does/does not work. I believe I read that "rotation goes wrong/unexpected when using scaling at the same time", but that is all I know. I believe there is a further complication that there are two ways to achieve rotation, either via QTransform::rotate() or via QGraphicsItem::setRotation(). I am unsure whether these are identical. I think there is a difference. Be sure to read https://doc.qt.io/qt-6/qgraphicsitem.html#transformations, including where it lists "QGraphicsItem always applies the properties in a fixed, defined order".

                    S Offline
                    S Offline
                    StudentScripter
                    wrote on 28 Aug 2024, 13:21 last edited by
                    #11

                    @JonB Well the real problem seems to be that rect().setTopLeft() and all other direct changes to the parentitems rect result in a changed Origin Point of the object in the scene, while with setScale() the OriginPoint stays intact.
                    Anyone else does know more about that? @Christian-Ehrlicher @SGaist maybe?

                    Pl45m4P 1 Reply Last reply 28 Aug 2024, 13:48
                    0
                    • S StudentScripter
                      28 Aug 2024, 13:21

                      @JonB Well the real problem seems to be that rect().setTopLeft() and all other direct changes to the parentitems rect result in a changed Origin Point of the object in the scene, while with setScale() the OriginPoint stays intact.
                      Anyone else does know more about that? @Christian-Ehrlicher @SGaist maybe?

                      Pl45m4P Online
                      Pl45m4P Online
                      Pl45m4
                      wrote on 28 Aug 2024, 13:48 last edited by Pl45m4
                      #12

                      @StudentScripter said in QGraphicsRectItem item translation instead of movement?:

                      Well the real problem seems to be that rect().setTopLeft() and all other direct changes to the parentitems rect result in a changed Origin Point of the object in the scene, while with setScale() the OriginPoint stays intact.

                      AFAIK the "topLeft" of an item rotated by 90° clockwise is still the same point as when not being transformed... the original item stays the same, because you can revert the transformation at any time to get your initial item back. The QTranform only "maps" the initial item matrix to your transformed one.
                      So I think calling setTopLeft manually will mess up your item and the current transformation completely.


                      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                      ~E. W. Dijkstra

                      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