Making QGraphicsScene bigger when a graphic item is placed against its border

折月煮酒 提交于 2021-02-08 05:17:48

问题


I've made a QGraphicsScene with a mouseClickEvent that lets the user create blue squares inside of it. But I want to make the scene grow when an item is placed against its border so that the user never runs out of space on the graphics scene.

What's the best way to make a graphics scene bigger in this case?


回答1:


I suggest doing something like the following:

  1. Get the bounding rect of all items in the scene using QGraphicsScene::itemsBoundingRect().
  2. Add some padding around that rect to make sure the bounds of the items won't hit the edge of the view. Something like myRect.adjust(-20, -20, 20, 20) should be sufficient.
  3. Use QGraphicsView::fitInView(myRect, Qt::KeepAspectRatio) to ensure the taken area is within the visible bounds of the view.

That should do it. This code should be called whenever something has changed in the scene. You can use QRectF::intersects() function to find out if the new rect has been placed on the edge of the view.

What's the best way to make a graphics scene bigger in this case?

The GraphicsScene is an infinite coordinate system. Most clients will use itemsBoundingRect() to get an idea how much space is actually used by items in the scene. If you have cleared the scene, you might want to call QGraphicsScene::setSceneRect(QRectF()) to "make it smaller" again.

Hope that helps.




回答2:


sorry if this is a little bit late(6 years) but I will provide an answer if someone still struggling with this or want another approach.I implement this in mouseReleaseEvent in the custom class derive from QGraphicsObject. Note that I initialize the size of my QGraphicsScene (1000,1000) with the following code.scene->setSceneRect(0,0,1000,1000). So here what my code will do. If the Item(the item is draggable) placed against the border, that border will increase. So here is my code:

void MyItem::mouseReleaseEvent(QgraphicsceneMouseEvent* event){
  QRectF tempRect = this->scene()->sceneRect();
  if(this->scenePos().y() < this->scene()->sceneRect().top()){
      tempRect.adjust(0,-200,0,0);
      if(this->scenePos().x() < this->scene()->sceneRect().left()){
          tempRect.adjust(-200,0,0,0);
      }
      else if(this->scenePos().x() + 200> this->scene()->sceneRect().right()){
        tempRect.adjust(0,0,200,0);
      }
  }
  else if(this->scenePos().y() + 200 > this->scene()->sceneRect().bottom()){
      tempRect.adjust(0,0,0,200);
      if(this->scenePos().x() < this->scene()->sceneRect().left()){
          tempRect.adjust(-200,0,0,0);
     }
     else if(this->scenePos().x() + 200> this->scene()->sceneRect().right()){
        tempRect.adjust(0,0,200,0);
     }
 }
 else if(this->scenePos().x() < this->scene()->sceneRect().left()){
      tempRect.adjust(-200,0,0,0);
      if(this->scenePos().y() < this->scene()->sceneRect().top()){
          tempRect.adjust(0,-200,0,0);
      }
      else if(this->scenePos().y() + 200 > this->scene()->sceneRect().bottom()){
          tempRect.adjust(0,0,0,200);
      }
  }
  else if(this->scenePos().x() + 200> this->scene()->sceneRect().right()){
      tempRect.adjust(0,0,200,0);
      if(this->scenePos().y() < this->scene()->sceneRect().top()){
          tempRect.adjust(0,-200,0,0);
      }
      else if(this->scenePos().y() + 200 > this->scene()->sceneRect().bottom()){
          tempRect.adjust(0,0,0,200);
      }
  }

  this->scene()->setSceneRect(tempRect);



回答3:


I know its late, but for anyone looking for python code here:

class Scene(QtWidgets.QGraphicsScene):
    def __init__(self):
        super(Scene, self).__init__()
        self.setSceneRect(0, 0, 2000, 2000)

        self.sceneRect().adjust(-20, -20, 20, 20)
        self.old_rect = self.itemsBoundingRect()

    def adjust(self):
        w = self.sceneRect().width()
        h = self.sceneRect().height()
        x = self.sceneRect().x()
        y = self.sceneRect().y()
        adjust_factor = 500
        adjust_factor2 = 300

        smaller = self.is_smaller()
        self.old_rect = self.itemsBoundingRect()

        if not self.sceneRect().contains(self.old_rect):
            self.setSceneRect(-adjust_factor + x, -adjust_factor + y, adjust_factor + w, adjust_factor + h)

        if smaller:
            self.setSceneRect(adjust_factor2 + x, adjust_factor2 + y, abs(adjust_factor2 - w), abs(adjust_factor2 - h))

    def is_smaller(self):

        x = self.old_rect.x()
        y = self.old_rect.y()

        h = self.old_rect.height()
        w = self.old_rect.width()

        if ((x <= self.itemsBoundingRect().x()) and (y <= self.itemsBoundingRect().y())
                and (h > self.itemsBoundingRect().height()) and (w > self.itemsBoundingRect().width())):
            return True

        return False

Explanation:

  1. use self.sceneRect().contains(self.itemBoundingRect) check whether the itemBoundingRect is within the sceneRect, if its not in the sceneRect then use self.setSceneRect() to increase the sceneRect size (Note: make sure you add to the previous sceneRect like shown in the above code).

  2. If you also want to decrease the sceneRect. Store the old itemBoundingRect and compare it with the new one, if the new itemSceneRect Rectangle is smaller then decrease the size by some factor (refer to the above code).

Usage:

you may call the adjust method from anywhere you like. But Calling the adjust method from mouseReleaseEvent worked the best for me.

*If you have any suggestions or query you may comment.



来源:https://stackoverflow.com/questions/4237387/making-qgraphicsscene-bigger-when-a-graphic-item-is-placed-against-its-border

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!