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. GraphicsScene: Grouping multiple Items Transforms (resize)
QtWS25 Last Chance

GraphicsScene: Grouping multiple Items Transforms (resize)

Scheduled Pinned Locked Moved Unsolved General and Desktop
qgraphicsitemqgraphicssceneqt c++
11 Posts 2 Posters 1.2k 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

    So i created handles for my graphicsitems which let me resize the items in the scene. The handles always take the selected Item as owner/parent. Now when i select multiple items i want all selected items to be grouped and the handles should be set to the new big selection rect transforming all items within it at once. Is this possible? What would be the best way to do that in the graphicsscene? GroupItem or set parent of the item maybe?

    #include "handleitem.h"
    #include "resizablehandlerect.h"
    #include <QGraphicsSceneMouseEvent>
    #include <QDebug>
    
    
    HandleItem::HandleItem(Position position) :
        handlePosition(position)
    {
        setFlag(QGraphicsItem::ItemIsMovable);
    }
    
    void HandleItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
    
        ResizableHandleRect *rectItem = dynamic_cast<ResizableHandleRect *>(parentItem());
    
        if (!rectItem) {
            return; // Wenn das Parent-Item kein ResizableHandleRect ist, beende die Funktion
        }
    
        QRectF boundingFrameRect = rectItem->selectorFrameBounds();
        
    
    
    
    
        switch (handlePosition) {
        case TopLeft:
            qDebug() << "Case TOPLeft:" << event->pos();
            boundingFrameRect.setTopLeft(event->pos() + QPointF(6, 6));
            break;
    
        case TopCenter:
            qDebug() << "Case TOP_Center:" << event->pos() + QPointF(+6,0) << "SelectoFrameBounds: "<< boundingFrameRect;
            boundingFrameRect.setTop(event->pos().y() + 6);
            break;
    
        case TopRight:
            qDebug() << "Case TOPRight:" << event->pos();
            boundingFrameRect.setTopRight(event->pos() + QPointF(-6, 6));
            break;
    
        case RightCenter:
            qDebug() << "Case RightCenter:" << event->pos();
            boundingFrameRect.setRight(event->pos().x() - 6);
            break;
    
        case BottomRight:
            qDebug() << "Case BOTTOMRight:" << event->pos();
            boundingFrameRect.setBottomRight(event->pos() + QPointF(-6, -6));
            break;
    
        case BottomCenter:
            qDebug() << "Case BottomCenter:" << event->pos();
            boundingFrameRect.setBottom(event->pos().y() - 6);
            break;
    
        case BottomLeft:
            qDebug() << "Case BOTTOMLeft:" << event->pos();
            boundingFrameRect.setBottomLeft(event->pos() + QPointF(6, -6));
            break;
    
        case LeftCenter:
            qDebug() << "Case LeftCenter:" << event->pos();
            boundingFrameRect.setLeft(event->pos().x() + 6);
            break;
    
        default:
            break;
        }
    
        rectItem->setSelectorFrameBounds(boundingFrameRect.normalized());
    
    }
    
    
    #include "resizablehandlerect.h"
    #include <QGraphicsScene>
    #include <QDebug>
    #include <QCursor>
    
    
    ResizableHandleRect::ResizableHandleRect()
    {
        
    
    
    }
    
    ResizableHandleRect::~ResizableHandleRect()
    {
    
    }
    
    void ResizableHandleRect::drawHandles()
    {
    
    
        // Erstellen und Hinzufügen der Handles zur Szene
    
        //Populate handles in list
        if(handleList.count() == 0){
            handleList.append(new HandleItem(HandleItem::TopLeft));
        handleList.append(new HandleItem(HandleItem::TopCenter));
            handleList.append(new HandleItem(HandleItem::TopRight));
        handleList.append(new HandleItem(HandleItem::RightCenter));   
            handleList.append(new HandleItem(HandleItem::BottomRight));
        handleList.append(new HandleItem(HandleItem::BottomCenter));  
            handleList.append(new HandleItem(HandleItem::BottomLeft));
        handleList.append(new HandleItem(HandleItem::LeftCenter));  
            
        }
    
    
    
        //Set up pen
        QPen mPen;
        mPen.setWidth(2);
        mPen.setColor(Qt::black);
        
        //Top left handle
        QPointF topLeftCorner = selectorFrameBounds().topLeft() + QPointF(-8.0,-8.0);
        topLeftHandleRect  = QRectF(topLeftCorner,QSize(8,8));
        handleList[0]->setRect(topLeftHandleRect);
        if(!handleList.isEmpty() && (!handlesAddedToScene)){
            handleList[0]->setPen(mPen);
            //handleList[0]->setBrush(QBrush(Qt::black)); 
            ownerItem->scene()->addItem(handleList[0]);
            handleList[0]->setParentItem(ownerItem);
            handleList[0]->setCursor(Qt::SizeFDiagCursor);
        }
        
    
                //Top Center
               QPointF topCenterCorner = QPointF(selectorFrameBounds().left() + selectorFrameBounds().width() / 2.0 - 4.0, selectorFrameBounds().top()-4.0);
                topCenterHandleRect  = QRectF(topCenterCorner,QSize(8,8));
                handleList[1]->setRect(topCenterHandleRect);
                if(!handleList.isEmpty() && (!handlesAddedToScene)){
                    handleList[1]->setPen(mPen);
                    //handleList[1]->setBrush(QBrush(Qt::gray));
                    ownerItem->scene()->addItem(handleList[1]);
                    handleList[1]->setParentItem(ownerItem);
                    handleList[1]->setCursor(Qt::SizeVerCursor);
                }
                
        
        
    
        //Top right
        QPointF topRightCorner = selectorFrameBounds().topRight() + QPointF(0,-8.0);
        topRightHandleRect  = QRectF(topRightCorner,QSize(8,8));
        handleList[2]->setRect(topRightHandleRect);
        if(!handleList.isEmpty() && (!handlesAddedToScene)){
            handleList[2]->setPen(mPen);
            //handleList[1]->setBrush(QBrush(Qt::gray));
            ownerItem->scene()->addItem(handleList[2]);
            handleList[2]->setParentItem(ownerItem);
            handleList[2]->setCursor(Qt::SizeBDiagCursor);
        }
    
    
                //Right Center
                QPointF rightCenterCorner = QPointF(selectorFrameBounds().right() - 4.0, selectorFrameBounds().top() + selectorFrameBounds().height() / 2.0 - 4.0);
                rightCenterHandleRect = QRectF(rightCenterCorner, QSize(8, 8));
                handleList[3]->setRect(rightCenterHandleRect);
                if (!handleList.isEmpty() && (!handlesAddedToScene)) {
                    handleList[3]->setPen(mPen);
                    ownerItem->scene()->addItem(handleList[3]);
                    handleList[3]->setParentItem(ownerItem);
                    handleList[3]->setCursor(Qt::SizeHorCursor);
                }
    
    
        //Bottom right
        QPointF bottomRightCorner = selectorFrameBounds().bottomRight() + QPointF(0,0);
        bottomRightHandleRect  = QRectF(bottomRightCorner,QSize(8,8));
        handleList[4]->setRect(bottomRightHandleRect);
        if(!handleList.isEmpty() && (!handlesAddedToScene)){
            handleList[4]->setPen(mPen);
            //handleList[2]->setBrush(QBrush(Qt::gray));
            ownerItem->scene()->addItem(handleList[4]);
            handleList[4]->setParentItem(ownerItem);
            handleList[4]->setCursor(Qt::SizeFDiagCursor);
        }
    
    
                
                // Bottom Center
                QPointF bottomCenterCorner = QPointF(selectorFrameBounds().left() + selectorFrameBounds().width() / 2.0 - 4.0, selectorFrameBounds().bottom()-4.0);
                bottomCenterHandleRect = QRectF(bottomCenterCorner, QSize(8, 8));
                handleList[5]->setRect(bottomCenterHandleRect);
                if (!handleList.isEmpty() && (!handlesAddedToScene)) {
                    handleList[5]->setPen(mPen);
                    ownerItem->scene()->addItem(handleList[5]);
                    handleList[5]->setParentItem(ownerItem);
                    handleList[5]->setCursor(Qt::SizeVerCursor);
                }
    
    
        //Bottom left
        QPointF bottomLeftCorner = selectorFrameBounds().bottomLeft() + QPointF(-8,0);
        bottomLeftHandleRect  = QRectF(bottomLeftCorner,QSize(8,8));
        handleList[6]->setRect(bottomLeftHandleRect);
        if(!handleList.isEmpty() && (!handlesAddedToScene)){
            handleList[6]->setPen(mPen);
            //handleList[3]->setBrush(QBrush(Qt::gray));
            ownerItem->scene()->addItem(handleList[6]);
            handleList[6]->setParentItem(ownerItem);
            handleList[6]->setCursor(Qt::SizeBDiagCursor);
        }
    
    
    
    
           
              // Left Center
                QPointF leftCenterCorner = QPointF(selectorFrameBounds().left() - 4.0, selectorFrameBounds().top() + selectorFrameBounds().height() / 2.0 - 4.0);
                leftCenterHandleRect = QRectF(leftCenterCorner, QSize(8, 8));
                handleList[7]->setRect(leftCenterHandleRect);
                if (!handleList.isEmpty() && (!handlesAddedToScene)) {
                    handleList[7]->setPen(mPen);
                    ownerItem->scene()->addItem(handleList[7]);
                    handleList[7]->setParentItem(ownerItem);
                    handleList[7]->setCursor(Qt::SizeHorCursor);
                }
    
    
    
    
        handlesAddedToScene = true;
    
    }
    
    
    
    
    
    
    
    
    void ResizableHandleRect::setOwnerItem(QGraphicsItem *value)
    {
        ownerItem = value;
        
    
    }
    
    
    
    
    void ResizableHandleRect::drawHandlesIfNecessary(bool ShouldDrawHandles)
    {
        if(!ownerItem){
            qWarning() << "ResizableHandleRect : No ownerItem set. Not drawing any\
                          handle. Please call setOwnerItem on your ResizableHandleRect subclass";
                          return;
        }
    
    
    
        if(ownerItem->isSelected() && ShouldDrawHandles == true){
            drawHandles();
            handlesAddedToScene = true;
    
            
            
        }else if(!ownerItem->isSelected() | ShouldDrawHandles == false){
    
            //Remove the handles
            foreach (HandleItem * handleItem, handleList) {
                ownerItem->scene()->removeItem(handleItem);
            
            }
            qDeleteAll(handleList);
            handleList.clear();
            handlesAddedToScene = false;
        }
    
    }
    
    
    
    
    
    
    
    
    Pl45m4P Online
    Pl45m4P Online
    Pl45m4
    wrote on last edited by Pl45m4
    #2

    @StudentScripter

    A temporary QGraphicsItemGroup might work.
    You can even draw a rect around the group to see what area you are moving or resizing. Then you can draw the handle.

    The boundingRect() function of QGraphicsItemGroup returns the bounding rectangle of all items in the item group. QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its children (i.e., with respect to the geometry of the group item, the children are treated as if they were transformable).

    • https://doc.qt.io/qt-6/qgraphicsitemgroup.html#details

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

    ~E. W. Dijkstra

    S 1 Reply Last reply
    1
    • Pl45m4P Pl45m4

      @StudentScripter

      A temporary QGraphicsItemGroup might work.
      You can even draw a rect around the group to see what area you are moving or resizing. Then you can draw the handle.

      The boundingRect() function of QGraphicsItemGroup returns the bounding rectangle of all items in the item group. QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its children (i.e., with respect to the geometry of the group item, the children are treated as if they were transformable).

      • https://doc.qt.io/qt-6/qgraphicsitemgroup.html#details
      S Offline
      S Offline
      StudentScripter
      wrote on last edited by StudentScripter
      #3

      @Pl45m4 Yes had a look at that and subclassed QGraphicsItemGroup and also inherited from resizablehandlerect. I wanted to override the paint event to trigger painting the handles but the paint event receives no signal at all.

      #ifndef RESIZABLEGRAPHICSGROUPITEM_H
      #define RESIZABLEGRAPHICSGROUPITEM_H
      
      
      #include <QGraphicsItemGroup>
      #include "resizablehandlerect.h"
      
      class ResizableGraphicsGroupItem : public QGraphicsItemGroup, public ResizableHandleRect
      {
      
      public:
          explicit ResizableGraphicsGroupItem();
      
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
      
      
      signals:
      
      
      
      };
      
      
      #endif // RESIZABLEGRAPHICSGROUPITEM_H
      
      

      Also im trying this in my scene but somehow it crashes:

      
      void CustomGraphicsScene::onSelectionChanged()
      {
          if (!isUpdatingSelection) {
              QList<QGraphicsItem*> selectedItemsList = this->selectedItems();
              QList<QStandardItem*> standardItemsList;
      
      
      
              // Durchlaufe alle ausgewählten Elemente
              foreach (QGraphicsItem* graphicsItem, selectedItemsList) {
                  QStandardItem* standardItem = FindListItemFromGraphicsItem(graphicsItem);
      
                  if (standardItem) {
                      // Füge das gefundene QStandardItem zur Liste hinzu
                      standardItemsList.append(standardItem);
                  }
              }
      
      
      
      
      
              if (selectedItemsList.count() > 1) {
                  // Erstellen Sie eine neue Gruppe
                  
                  if (GroupSelectionRect) {
                      this->destroyItemGroup(GroupSelectionRect);
                      this->removeItem(GroupSelectionRect);
                      delete GroupSelectionRect;
                  }
      
      
      
      
      
                  GroupSelectionRect = new ResizableGraphicsGroupItem();
      
              
                  // Fügen Sie die ausgewählten Elemente zur Gruppe hinzu
                  foreach (QGraphicsItem* item, selectedItemsList) {
                      GroupSelectionRect->addToGroup(item);
                  }
      
                  // Fügen Sie die Gruppe zur Szene hinzu
                  this->addItem(GroupSelectionRect);
              }
      
      
      
      
              emit SendSelectionChangedFromSceneToLayerList(standardItemsList);
          }
      
      
      
      
          // Deine Logik zur Verarbeitung der ausgewählten Elemente
          this->update();
      }
      
      
      
      Pl45m4P 1 Reply Last reply
      0
      • S StudentScripter

        @Pl45m4 Yes had a look at that and subclassed QGraphicsItemGroup and also inherited from resizablehandlerect. I wanted to override the paint event to trigger painting the handles but the paint event receives no signal at all.

        #ifndef RESIZABLEGRAPHICSGROUPITEM_H
        #define RESIZABLEGRAPHICSGROUPITEM_H
        
        
        #include <QGraphicsItemGroup>
        #include "resizablehandlerect.h"
        
        class ResizableGraphicsGroupItem : public QGraphicsItemGroup, public ResizableHandleRect
        {
        
        public:
            explicit ResizableGraphicsGroupItem();
        
          void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
        
        
        signals:
        
        
        
        };
        
        
        #endif // RESIZABLEGRAPHICSGROUPITEM_H
        
        

        Also im trying this in my scene but somehow it crashes:

        
        void CustomGraphicsScene::onSelectionChanged()
        {
            if (!isUpdatingSelection) {
                QList<QGraphicsItem*> selectedItemsList = this->selectedItems();
                QList<QStandardItem*> standardItemsList;
        
        
        
                // Durchlaufe alle ausgewählten Elemente
                foreach (QGraphicsItem* graphicsItem, selectedItemsList) {
                    QStandardItem* standardItem = FindListItemFromGraphicsItem(graphicsItem);
        
                    if (standardItem) {
                        // Füge das gefundene QStandardItem zur Liste hinzu
                        standardItemsList.append(standardItem);
                    }
                }
        
        
        
        
        
                if (selectedItemsList.count() > 1) {
                    // Erstellen Sie eine neue Gruppe
                    
                    if (GroupSelectionRect) {
                        this->destroyItemGroup(GroupSelectionRect);
                        this->removeItem(GroupSelectionRect);
                        delete GroupSelectionRect;
                    }
        
        
        
        
        
                    GroupSelectionRect = new ResizableGraphicsGroupItem();
        
                
                    // Fügen Sie die ausgewählten Elemente zur Gruppe hinzu
                    foreach (QGraphicsItem* item, selectedItemsList) {
                        GroupSelectionRect->addToGroup(item);
                    }
        
                    // Fügen Sie die Gruppe zur Szene hinzu
                    this->addItem(GroupSelectionRect);
                }
        
        
        
        
                emit SendSelectionChangedFromSceneToLayerList(standardItemsList);
            }
        
        
        
        
            // Deine Logik zur Verarbeitung der ausgewählten Elemente
            this->update();
        }
        
        
        
        Pl45m4P Online
        Pl45m4P Online
        Pl45m4
        wrote on last edited by Pl45m4
        #4

        @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

        Yes had a look at that and subclassed QGraphicsItemGroup and also inherited from resizablehandlerect. I wanted to override the paint event to trigger painting the handles but the paint event receives no signal at all.

        What kind of class is ResizableHandleRect?
        Neither QGraphicsItem nor QGraphicsItemGroup is a QObject, so you can't use Signals and Slots there.
        But if ResizableHandleRect is a QObject, you need to switch the order of inheritance. Always inherit from the QObject based class first when using multiple inheritance.


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

        ~E. W. Dijkstra

        S 2 Replies Last reply
        2
        • Pl45m4P Pl45m4

          @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

          Yes had a look at that and subclassed QGraphicsItemGroup and also inherited from resizablehandlerect. I wanted to override the paint event to trigger painting the handles but the paint event receives no signal at all.

          What kind of class is ResizableHandleRect?
          Neither QGraphicsItem nor QGraphicsItemGroup is a QObject, so you can't use Signals and Slots there.
          But if ResizableHandleRect is a QObject, you need to switch the order of inheritance. Always inherit from the QObject based class first when using multiple inheritance.

          S Offline
          S Offline
          StudentScripter
          wrote on last edited by
          #5

          @Pl45m4 Alright gonna check this out. ResizableHandleRect is a QGraphicsRectItem so yeah... :D

          1 Reply Last reply
          0
          • Pl45m4P Pl45m4

            @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

            Yes had a look at that and subclassed QGraphicsItemGroup and also inherited from resizablehandlerect. I wanted to override the paint event to trigger painting the handles but the paint event receives no signal at all.

            What kind of class is ResizableHandleRect?
            Neither QGraphicsItem nor QGraphicsItemGroup is a QObject, so you can't use Signals and Slots there.
            But if ResizableHandleRect is a QObject, you need to switch the order of inheritance. Always inherit from the QObject based class first when using multiple inheritance.

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

            @Pl45m4 So i checked it, but now i have a issue with actually adding items to the rect:
            On the first time selecting the selection rect is created, but on the second time it only adds 1 item to the selection rect while the other items stay selected:

            
            CustomGraphicsScene::CustomGraphicsScene(QObject *parent)
                : QGraphicsScene(parent)
            {
            //Erstellt die Hauptinstanz des UndoStack
            undoStack = new QUndoStack(this);
                
                
                //Setzt die generelle Hintergrundfarbe für die gesamte Scene
                setBackgroundBrush(Qt::gray);
              
                //Höhe & Breite, setzt das eigentliche SceneRect
                SceneRectWidth = 900;
                SceneRectHeight = 600;
                setSceneRect(QRectF(0, 0, SceneRectWidth, SceneRectHeight));
                
                
            
                    if (!connect(this, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()))) {
                        qDebug() << "Failed to connect signal and slot";
                    }
            
            
                       GroupSelectionRect = new ResizableGraphicsGroupItem();
                    addItem(GroupSelectionRect);
            
            }
            
            
            CustomGraphicsScene::~CustomGraphicsScene()
            {
               disconnect(this, &QGraphicsScene::selectionChanged, this, &CustomGraphicsScene::onSelectionChanged);
            
                qDebug() << "isDestructed";
            }
            
            
            
            
            void CustomGraphicsScene::onSelectionChanged()
            {
            
            
            
            
            
            qDebug() << "selectedItems_" << selectedItems().count() << selectedItems();
            if (selectedItems().count() > 1) {
            
            
                // Clear the previous items from the group
                if (GroupSelectionRect) {
            
                    if (GroupSelectionRect) {
                        // Durchlaufe jedes Element in der Gruppe
                        foreach (QGraphicsItem* item, GroupSelectionRect->childItems()) {
                            // Entferne das Element aus der Gruppe
                            GroupSelectionRect->removeFromGroup(item);
            
                        }
                    }
            
            
                    qDebug() << "GroupSelChilds:" << GroupSelectionRect->childItems();
            
            
                    // Durchlaufe alle ausgewählten Elemente erneut, füge sie zur Gruppe hinzu
                    foreach (QGraphicsItem* graphicsItem, selectedItems()) {
                        ResizablePixmapItem* rectItem = dynamic_cast<ResizablePixmapItem*>(graphicsItem);
                        if (rectItem) {
                            //rectItem->drawHandlesIfNecessary(false);
                            // Füge das GraphicsItem zur Gruppe hinzu
                            GroupSelectionRect->addToGroup(rectItem);
            
                        }
            
                    }
                }
            
            }
            
            qDebug() << "GroupSelChilds:" << GroupSelectionRect->childItems();
            
            
            
            
            
            

            Here is a explanation with pictures:
            1) im adding 2 items to the scene:
            2e8a80fa-8975-420c-8c2f-8f39f0927e7d-image.png
            2) im selecting both the selection rect gets created:
            b58a3349-c71b-4533-8280-fd32dac3ea28-image.png
            3) im adding a 3rd item and trying to select the 3rd and the 2nd item: (but here suddenly all 3 items get selected and only the 3rd item gets the groupitemrect
            891e61e4-0bbe-4a19-bd5d-7b6fd9833b66-image.png

            Pl45m4P 1 Reply Last reply
            0
            • S StudentScripter

              @Pl45m4 So i checked it, but now i have a issue with actually adding items to the rect:
              On the first time selecting the selection rect is created, but on the second time it only adds 1 item to the selection rect while the other items stay selected:

              
              CustomGraphicsScene::CustomGraphicsScene(QObject *parent)
                  : QGraphicsScene(parent)
              {
              //Erstellt die Hauptinstanz des UndoStack
              undoStack = new QUndoStack(this);
                  
                  
                  //Setzt die generelle Hintergrundfarbe für die gesamte Scene
                  setBackgroundBrush(Qt::gray);
                
                  //Höhe & Breite, setzt das eigentliche SceneRect
                  SceneRectWidth = 900;
                  SceneRectHeight = 600;
                  setSceneRect(QRectF(0, 0, SceneRectWidth, SceneRectHeight));
                  
                  
              
                      if (!connect(this, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()))) {
                          qDebug() << "Failed to connect signal and slot";
                      }
              
              
                         GroupSelectionRect = new ResizableGraphicsGroupItem();
                      addItem(GroupSelectionRect);
              
              }
              
              
              CustomGraphicsScene::~CustomGraphicsScene()
              {
                 disconnect(this, &QGraphicsScene::selectionChanged, this, &CustomGraphicsScene::onSelectionChanged);
              
                  qDebug() << "isDestructed";
              }
              
              
              
              
              void CustomGraphicsScene::onSelectionChanged()
              {
              
              
              
              
              
              qDebug() << "selectedItems_" << selectedItems().count() << selectedItems();
              if (selectedItems().count() > 1) {
              
              
                  // Clear the previous items from the group
                  if (GroupSelectionRect) {
              
                      if (GroupSelectionRect) {
                          // Durchlaufe jedes Element in der Gruppe
                          foreach (QGraphicsItem* item, GroupSelectionRect->childItems()) {
                              // Entferne das Element aus der Gruppe
                              GroupSelectionRect->removeFromGroup(item);
              
                          }
                      }
              
              
                      qDebug() << "GroupSelChilds:" << GroupSelectionRect->childItems();
              
              
                      // Durchlaufe alle ausgewählten Elemente erneut, füge sie zur Gruppe hinzu
                      foreach (QGraphicsItem* graphicsItem, selectedItems()) {
                          ResizablePixmapItem* rectItem = dynamic_cast<ResizablePixmapItem*>(graphicsItem);
                          if (rectItem) {
                              //rectItem->drawHandlesIfNecessary(false);
                              // Füge das GraphicsItem zur Gruppe hinzu
                              GroupSelectionRect->addToGroup(rectItem);
              
                          }
              
                      }
                  }
              
              }
              
              qDebug() << "GroupSelChilds:" << GroupSelectionRect->childItems();
              
              
              
              
              
              

              Here is a explanation with pictures:
              1) im adding 2 items to the scene:
              2e8a80fa-8975-420c-8c2f-8f39f0927e7d-image.png
              2) im selecting both the selection rect gets created:
              b58a3349-c71b-4533-8280-fd32dac3ea28-image.png
              3) im adding a 3rd item and trying to select the 3rd and the 2nd item: (but here suddenly all 3 items get selected and only the 3rd item gets the groupitemrect
              891e61e4-0bbe-4a19-bd5d-7b6fd9833b66-image.png

              Pl45m4P Online
              Pl45m4P Online
              Pl45m4
              wrote on last edited by Pl45m4
              #7

              @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

              1. im adding a 3rd item and trying to select the 3rd and the 2nd item: (but here suddenly all 3 items get selected and only the 3rd item gets the groupitemrect

              Because your logic behind this seems tempting to "simply" do as you did, but is wrong (doesn't work as you might expect).

              See QGraphicsScene::selectionChanged()

              • https://doc.qt.io/qt-6/qgraphicsscene.html#selectionChanged

              The selection changes whenever an item is selected or unselected, a selection area is set, cleared or otherwise changed, if a preselected item is added to the scene, or if a selected item is removed from the scene.

              QGraphicsScene emits this signal only once for group selection operations. For example, if you set a selection area, select or unselect a QGraphicsItemGroup, or if you add or remove from the scene a parent item that contains several selected items, selectionChanged() is emitted only once after the operation has completed (instead of once for each item).

              The standard selection bahavior is like this (nothing special):

              ItemSelection.gif

              If you add your QGraphicsItemGroup the way you do currently, you get this:
              It's not 100% the same, because I'm not selecting all at once by using some rubberband rect, but the root of the misbehavior should be the same.
              ItemSelectionGroup.gif

              See how the selectedItems() counter returned from QGraphicsScene changes?
              You would expect it to behave like it does without the group: One at a time... Counter goes from 1 to 10 and adding one after another to the group.

              But, since QGraphicsItemsGroup is a QGraphicsItems itself, it shadows all selected items which are part of it.

              Therefore the QGraphicsScene, i.e.
              your line here

              if (selectedItems().count() > 1) 
              

              would count

              0, 1, 0, 1, 0, 1
              

              because all previously (more than 2) selectedItems are added to the group, which itself, is unselected.
              So everything the scene sees, is the group containing X selected items, but counting 0 plus a maximum of one additional selected item, which was not added due to if (selectedItems().count() > 1) and the fact that every change (see signal doc.) triggers the signal.

              When you select a second one, it's added again and the scene is left with 0 selected items (= the group).

              So add some own logic to count group and non-group members or move the counting away from a function directly connected to selectionChanged().

              Edit:

              Btw: If you are planning to make your QGraphicsItemGroup selectable and movable, you could even run into some recursion, because then, at some point you would try to add the whole group item to ifself, which Qt obviously prevents.
              (Got the warning in my little example as I made the group selectable)


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

              ~E. W. Dijkstra

              S 1 Reply Last reply
              0
              • Pl45m4P Pl45m4

                @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

                1. im adding a 3rd item and trying to select the 3rd and the 2nd item: (but here suddenly all 3 items get selected and only the 3rd item gets the groupitemrect

                Because your logic behind this seems tempting to "simply" do as you did, but is wrong (doesn't work as you might expect).

                See QGraphicsScene::selectionChanged()

                • https://doc.qt.io/qt-6/qgraphicsscene.html#selectionChanged

                The selection changes whenever an item is selected or unselected, a selection area is set, cleared or otherwise changed, if a preselected item is added to the scene, or if a selected item is removed from the scene.

                QGraphicsScene emits this signal only once for group selection operations. For example, if you set a selection area, select or unselect a QGraphicsItemGroup, or if you add or remove from the scene a parent item that contains several selected items, selectionChanged() is emitted only once after the operation has completed (instead of once for each item).

                The standard selection bahavior is like this (nothing special):

                ItemSelection.gif

                If you add your QGraphicsItemGroup the way you do currently, you get this:
                It's not 100% the same, because I'm not selecting all at once by using some rubberband rect, but the root of the misbehavior should be the same.
                ItemSelectionGroup.gif

                See how the selectedItems() counter returned from QGraphicsScene changes?
                You would expect it to behave like it does without the group: One at a time... Counter goes from 1 to 10 and adding one after another to the group.

                But, since QGraphicsItemsGroup is a QGraphicsItems itself, it shadows all selected items which are part of it.

                Therefore the QGraphicsScene, i.e.
                your line here

                if (selectedItems().count() > 1) 
                

                would count

                0, 1, 0, 1, 0, 1
                

                because all previously (more than 2) selectedItems are added to the group, which itself, is unselected.
                So everything the scene sees, is the group containing X selected items, but counting 0 plus a maximum of one additional selected item, which was not added due to if (selectedItems().count() > 1) and the fact that every change (see signal doc.) triggers the signal.

                When you select a second one, it's added again and the scene is left with 0 selected items (= the group).

                So add some own logic to count group and non-group members or move the counting away from a function directly connected to selectionChanged().

                Edit:

                Btw: If you are planning to make your QGraphicsItemGroup selectable and movable, you could even run into some recursion, because then, at some point you would try to add the whole group item to ifself, which Qt obviously prevents.
                (Got the warning in my little example as I made the group selectable)

                S Offline
                S Offline
                StudentScripter
                wrote on last edited by
                #8

                @Pl45m4 said in GraphicsScene: Grouping multiple Items Transforms (resize):

                Btw: If you are planning to make your QGraphicsItemGroup selectable and movable, you could even run into some recursion, because then, at some point you would try to add the whole group item to ifself, which Qt obviously prevents.
                (Got the warning in my little example as I made the group selectable)

                Yes, it already is selectable and movable. So what whould you suggest instead? Also big thanks for the big effort you put into explaining, this helps a lot. <3 Have a nice evening.

                Pl45m4P 1 Reply Last reply
                0
                • S StudentScripter

                  @Pl45m4 said in GraphicsScene: Grouping multiple Items Transforms (resize):

                  Btw: If you are planning to make your QGraphicsItemGroup selectable and movable, you could even run into some recursion, because then, at some point you would try to add the whole group item to ifself, which Qt obviously prevents.
                  (Got the warning in my little example as I made the group selectable)

                  Yes, it already is selectable and movable. So what whould you suggest instead? Also big thanks for the big effort you put into explaining, this helps a lot. <3 Have a nice evening.

                  Pl45m4P Online
                  Pl45m4P Online
                  Pl45m4
                  wrote on last edited by
                  #9

                  @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

                  So what whould you suggest instead?

                  Find another way to keep track of the items which are members of the group.

                  Also I've noticed that selected items which are part of the group and get removed from the group desync and are painted in (wrong) selected state, even though they are not. So you have to restore they state somehow, if this occures.


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

                  ~E. W. Dijkstra

                  S 2 Replies Last reply
                  0
                  • Pl45m4P Pl45m4

                    @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

                    So what whould you suggest instead?

                    Find another way to keep track of the items which are members of the group.

                    Also I've noticed that selected items which are part of the group and get removed from the group desync and are painted in (wrong) selected state, even though they are not. So you have to restore they state somehow, if this occures.

                    S Offline
                    S Offline
                    StudentScripter
                    wrote on last edited by
                    #10

                    @Pl45m4 Gonna have a look. I'll post again when i may find a solution or atleast a good start. :D

                    1 Reply Last reply
                    0
                    • Pl45m4P Pl45m4

                      @StudentScripter said in GraphicsScene: Grouping multiple Items Transforms (resize):

                      So what whould you suggest instead?

                      Find another way to keep track of the items which are members of the group.

                      Also I've noticed that selected items which are part of the group and get removed from the group desync and are painted in (wrong) selected state, even though they are not. So you have to restore they state somehow, if this occures.

                      S Offline
                      S Offline
                      StudentScripter
                      wrote on last edited by
                      #11

                      @Pl45m4 Got i solved by just handling the selection in the mousepress and release event. However now im stuck with painting handles to resize the groupitem. I don't really know how to do that as qgraphicsgrouptitem has no setRect method.

                      Here is my graphicsgroupitem;

                      #include "resizablegraphicsgroupitem.h"
                      #include "qpainter.h"
                      #include <QPen>
                      
                      
                      
                      
                      ResizableGraphicsGroupItem::ResizableGraphicsGroupItem()
                      {
                          // Initialisierungen hier, falls benötigt
                          setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsScenePositionChanges | QGraphicsItem::ItemSendsGeometryChanges);
                          setOwnerItem(this);
                      
                      }
                      
                      QRectF ResizableGraphicsGroupItem::boundingRect() const
                      {
                      
                          return childrenBoundingRect();
                      }
                      
                      
                      
                      void ResizableGraphicsGroupItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
                      {
                          qDebug() << "Test";
                          Q_UNUSED(option);
                          Q_UNUSED(widget);
                          painter->save();
                      
                      
                      
                          //Malt eine Linie um das Rechteck
                          painter->setPen(QPen(Qt::green));
                          painter->drawRect(boundingRect());
                      
                      
                          painter->restore();
                      }
                      
                      
                      
                      
                      

                      I coded such a handle class before, but i don't know how to get it to work with a qgraphicsgroupitem:

                      #include "resizablehandlerect.h"
                      #include <QGraphicsScene>
                      #include <QDebug>
                      #include <QCursor>
                      
                      
                      ResizableHandleRect::ResizableHandleRect()
                      {
                          
                      
                      
                      }
                      
                      ResizableHandleRect::~ResizableHandleRect()
                      {
                      
                      }
                      
                      void ResizableHandleRect::drawHandles()
                      {
                          qDebug() << "ResizableHandleRect DrawHandles triggered!";
                      
                          // Erstellen und Hinzufügen der Handles zur Szene
                      
                          //Populate handles in list
                          if(handleList.count() == 0){
                              handleList.append(new HandleItem(HandleItem::TopLeft));
                          handleList.append(new HandleItem(HandleItem::TopCenter));
                              handleList.append(new HandleItem(HandleItem::TopRight));
                          handleList.append(new HandleItem(HandleItem::RightCenter));   
                              handleList.append(new HandleItem(HandleItem::BottomRight));
                          handleList.append(new HandleItem(HandleItem::BottomCenter));  
                              handleList.append(new HandleItem(HandleItem::BottomLeft));
                          handleList.append(new HandleItem(HandleItem::LeftCenter));  
                              
                          }
                      
                      
                      
                          //Set up pen
                          QPen mPen;
                          mPen.setWidth(2);
                          mPen.setColor(Qt::black);
                          
                          //Top left handle
                          QPointF topLeftCorner = selectorFrameBounds().topLeft() + QPointF(-8.0,-8.0);
                          topLeftHandleRect  = QRectF(topLeftCorner,QSize(8,8));
                          handleList[0]->setRect(topLeftHandleRect);
                          if(!handleList.isEmpty() && (!handlesAddedToScene)){
                              handleList[0]->setPen(mPen);
                              //handleList[0]->setBrush(QBrush(Qt::black)); 
                              ownerItem->scene()->addItem(handleList[0]);
                              handleList[0]->setParentItem(ownerItem);
                              handleList[0]->setCursor(Qt::SizeFDiagCursor);
                          }
                          
                      
                                  //Top Center
                                 QPointF topCenterCorner = QPointF(selectorFrameBounds().left() + selectorFrameBounds().width() / 2.0 - 4.0, selectorFrameBounds().top()-4.0);
                                  topCenterHandleRect  = QRectF(topCenterCorner,QSize(8,8));
                                  handleList[1]->setRect(topCenterHandleRect);
                                  if(!handleList.isEmpty() && (!handlesAddedToScene)){
                                      handleList[1]->setPen(mPen);
                                      //handleList[1]->setBrush(QBrush(Qt::gray));
                                      ownerItem->scene()->addItem(handleList[1]);
                                      handleList[1]->setParentItem(ownerItem);
                                      handleList[1]->setCursor(Qt::SizeVerCursor);
                                  }
                                  
                          
                          
                      
                          //Top right
                          QPointF topRightCorner = selectorFrameBounds().topRight() + QPointF(0,-8.0);
                          topRightHandleRect  = QRectF(topRightCorner,QSize(8,8));
                          handleList[2]->setRect(topRightHandleRect);
                          if(!handleList.isEmpty() && (!handlesAddedToScene)){
                              handleList[2]->setPen(mPen);
                              //handleList[1]->setBrush(QBrush(Qt::gray));
                              ownerItem->scene()->addItem(handleList[2]);
                              handleList[2]->setParentItem(ownerItem);
                              handleList[2]->setCursor(Qt::SizeBDiagCursor);
                          }
                      
                      
                                  //Right Center
                                  QPointF rightCenterCorner = QPointF(selectorFrameBounds().right() - 4.0, selectorFrameBounds().top() + selectorFrameBounds().height() / 2.0 - 4.0);
                                  rightCenterHandleRect = QRectF(rightCenterCorner, QSize(8, 8));
                                  handleList[3]->setRect(rightCenterHandleRect);
                                  if (!handleList.isEmpty() && (!handlesAddedToScene)) {
                                      handleList[3]->setPen(mPen);
                                      ownerItem->scene()->addItem(handleList[3]);
                                      handleList[3]->setParentItem(ownerItem);
                                      handleList[3]->setCursor(Qt::SizeHorCursor);
                                  }
                      
                      
                          //Bottom right
                          QPointF bottomRightCorner = selectorFrameBounds().bottomRight() + QPointF(0,0);
                          bottomRightHandleRect  = QRectF(bottomRightCorner,QSize(8,8));
                          handleList[4]->setRect(bottomRightHandleRect);
                          if(!handleList.isEmpty() && (!handlesAddedToScene)){
                              handleList[4]->setPen(mPen);
                              //handleList[2]->setBrush(QBrush(Qt::gray));
                              ownerItem->scene()->addItem(handleList[4]);
                              handleList[4]->setParentItem(ownerItem);
                              handleList[4]->setCursor(Qt::SizeFDiagCursor);
                          }
                      
                      
                                  
                                  // Bottom Center
                                  QPointF bottomCenterCorner = QPointF(selectorFrameBounds().left() + selectorFrameBounds().width() / 2.0 - 4.0, selectorFrameBounds().bottom()-4.0);
                                  bottomCenterHandleRect = QRectF(bottomCenterCorner, QSize(8, 8));
                                  handleList[5]->setRect(bottomCenterHandleRect);
                                  if (!handleList.isEmpty() && (!handlesAddedToScene)) {
                                      handleList[5]->setPen(mPen);
                                      ownerItem->scene()->addItem(handleList[5]);
                                      handleList[5]->setParentItem(ownerItem);
                                      handleList[5]->setCursor(Qt::SizeVerCursor);
                                  }
                      
                      
                          //Bottom left
                          QPointF bottomLeftCorner = selectorFrameBounds().bottomLeft() + QPointF(-8,0);
                          bottomLeftHandleRect  = QRectF(bottomLeftCorner,QSize(8,8));
                          handleList[6]->setRect(bottomLeftHandleRect);
                          if(!handleList.isEmpty() && (!handlesAddedToScene)){
                              handleList[6]->setPen(mPen);
                              //handleList[3]->setBrush(QBrush(Qt::gray));
                              ownerItem->scene()->addItem(handleList[6]);
                              handleList[6]->setParentItem(ownerItem);
                              handleList[6]->setCursor(Qt::SizeBDiagCursor);
                          }
                      
                      
                      
                      
                             
                                // Left Center
                                  QPointF leftCenterCorner = QPointF(selectorFrameBounds().left() - 4.0, selectorFrameBounds().top() + selectorFrameBounds().height() / 2.0 - 4.0);
                                  leftCenterHandleRect = QRectF(leftCenterCorner, QSize(8, 8));
                                  handleList[7]->setRect(leftCenterHandleRect);
                                  if (!handleList.isEmpty() && (!handlesAddedToScene)) {
                                      handleList[7]->setPen(mPen);
                                      ownerItem->scene()->addItem(handleList[7]);
                                      handleList[7]->setParentItem(ownerItem);
                                      handleList[7]->setCursor(Qt::SizeHorCursor);
                                  }
                      
                      
                      
                      
                          handlesAddedToScene = true;
                      
                      }
                      
                      
                      
                      
                      
                      
                      
                      
                      void ResizableHandleRect::setOwnerItem(QGraphicsItem *value)
                      {
                          ownerItem = value;
                          
                      
                      }
                      
                      
                      
                      
                      void ResizableHandleRect::drawHandlesIfNecessary(bool ShouldDrawHandles)
                      {
                          qDebug() << "DrawHandles" << ShouldDrawHandles << ownerItem->isSelected();
                          if(!ownerItem){
                              qWarning() << "ResizableHandleRect : No ownerItem set. Not drawing any\
                                            handle. Please call setOwnerItem on your ResizableHandleRect subclass";
                                            return;
                          }
                      
                      
                      
                          if(ownerItem->isSelected() && ShouldDrawHandles == true){
                              drawHandles();
                              handlesAddedToScene = true;
                      
                              
                              
                          }else if(!ownerItem->isSelected() | (ShouldDrawHandles == false)){
                      
                              //Remove the handles
                              foreach (HandleItem * handleItem, handleList) {
                                  ownerItem->scene()->removeItem(handleItem);
                              
                              }
                              qDeleteAll(handleList);
                              handleList.clear();
                              handlesAddedToScene = false;
                          }
                      
                      }
                      
                      
                      
                      
                      
                      
                      
                      
                      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