简体   繁体   English

当图形项靠在其边框上时使 QGraphicsScene 变大

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

I've made a QGraphicsScene with a mouseClickEvent that lets the user create blue squares inside of it.我制作了一个带有mouseClickEventQGraphicsScene ,它允许用户在其中创建蓝色方块。 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?在这种情况下,使图形场景变大的最佳方法是什么?

I suggest doing something like the following:我建议做类似下面的事情:

  1. Get the bounding rect of all items in the scene using QGraphicsScene::itemsBoundingRect() .使用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.myRect.adjust(-20, -20, 20, 20)这样的东西应该就足够了。
  3. Use QGraphicsView::fitInView(myRect, Qt::KeepAspectRatio) to ensure the taken area is within the visible bounds of the view.使用QGraphicsView::fitInView(myRect, Qt::KeepAspectRatio)确保拍摄区域在视图的可见范围内。

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.您可以使用 QRectF::intersects() 函数来查明新矩形是否已放置在视图的边缘。

What's the best way to make a graphics scene bigger in this case?在这种情况下,使图形场景变大的最佳方法是什么?

The GraphicsScene is an infinite coordinate system. GraphicsScene 是一个无限坐标系。 Most clients will use itemsBoundingRect() to get an idea how much space is actually used by items in the scene.大多数客户端将使用itemsBoundingRect()来了解场景中的项目实际使用了多少空间。 If you have cleared the scene, you might want to call QGraphicsScene::setSceneRect(QRectF()) to "make it smaller" again.如果你已经清除了场景,你可能想再次调用QGraphicsScene::setSceneRect(QRectF())来“缩小它”。

Hope that helps.希望有所帮助。

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 .抱歉,如果这有点晚(6 年),但如果有人仍在为此苦苦挣扎或想要另一种方法,我会提供答案。我在派生自QGraphicsObject的自定义类的mouseReleaseEvent中实现了这一点。 Note that I initialize the size of my QGraphicsScene (1000,1000) with the following code.请注意,我使用以下代码初始化了QGraphicsScene (1000,1000) 的大小。 scene->setSceneRect(0,0,1000,1000) . 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.如果 Item(该项目是可拖动的)靠着边框放置,则该边框将增加。 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);

I know its late, but for anyone looking for python code here:我知道它晚了,但对于在这里寻找 python 代码的任何人:

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).使用self.sceneRect().contains(self.itemBoundingRect)检查sceneRect是否在itemBoundingRect内,如果它不在sceneRect中然后使用self.setSceneRect()增加sceneRect大小(注意:确保你添加到以前sceneRect 如上面的代码所示)。

  2. If you also want to decrease the sceneRect .如果您还想减少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).存储旧的itemBoundingRect并将其与新的进行比较,如果新的itemSceneRect Rectangle 更小,则将尺寸缩小一些(参考上面的代码)。

Usage :用法

you may call the adjust method from anywhere you like.你可以从任何你喜欢的地方调用adjust方法。 But Calling the adjust method from mouseReleaseEvent worked the best for me.但是从mouseReleaseEvent调用adjust方法对我来说效果最好。

*If you have any suggestions or query you may comment. *如果您有任何建议或疑问,您可以发表评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM