代码之家  ›  专栏  ›  技术社区  ›  pbreach

无法在场景中正确定位QGraphicsRectItem

  •  2
  • pbreach  · 技术社区  · 8 年前

    我这辈子都搞不懂,但我把它归结为一个自我控制的问题。

    我想做的是画一个 QGraphicsRectItem QGraphicsScene 。绘制矩形后,可以将所有项目一起移动。我已经调查过了 QGraphicsItemGroup 已经决定在我的实际用例中不可行。

    问题是: 我已经完成了上面提到的所有事情, 除了 我无法正确定位矩形项目,即它的大小合适,通过移动它,所有项目都会移动,但它没有与所选项目的统一边界矩形对齐。我已经尝试将所有内容保持在场景坐标中,所以我不确定为什么会有偏移。

    为什么会出现抵消,如何缓解?

    #####The line where the position of the rect item is set is marked like this#####
    
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    import sys
    
    
    class DiagramScene(QGraphicsScene):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.selBox = None
            self.selectionChanged.connect(self.onSelectionChange)
    
        @pyqtSlot()
        def onSelectionChange(self):
            count = 0
            items = self.selectedItems()
    
            # Get bounding rect of all selected Items
            for item in self.selectedItems():
                if count == 0:
                    rect = item.mapRectToScene(item.boundingRect())
                else:
                    rect = rect.unite(item.mapRectToScene(item.boundingRect()))
                count += 1
    
            if count > 0:
                if self.selBox:
                    # Update selBox if items are selected and already exists
                    self.selBox.setRect(rect)
                    self.selBox.items = items
                else:
                    # Instantiate selBox if items are selected and does not already exist
                    self.selBox = DiagramSelBox(rect, items)
                    ##### Set position of selBox to topLeft corner of united rect #####
                    self.selBox.setPos(rect.topLeft())
                    self.addItem(self.selBox)
            elif self.selBox:
                # Remove selBox from scene if no items are selected and box is drawn
                self.removeItem(self.selBox)
                del self.selBox
                self.selBox = None
    
    
    class DiagramSelBox(QGraphicsRectItem):
        def __init__(self, bounds, items, parent=None, scene=None):
            super().__init__(bounds, parent, scene)
    
            self.setFlag(QGraphicsItem.ItemIsSelectable, True)
            self.pressPos = None
            self.items = items
    
        def paint(self, painter, option, widget=None):
            pen = QPen(Qt.DashLine)
            painter.setPen(pen)
            painter.drawRect(self.rect())
    
        def mousePressEvent(self, e):
            # Get original position of selBox when clicked
            self.pressPos = self.pos()
            # mouseEvent is not passed on to scene so item selection
            # does not change
    
        def mouseMoveEvent(self, e):
            super().mouseMoveEvent(e)
            if self.pressPos:
                # Move selBox is original position is set
                newPos = self.mapToScene(e.pos()) - self.rect().center()
                self.setPos(newPos)
    
        def mouseReleaseEvent(self, e):
            # Update position of all selected items
            change = self.scenePos() - self.pressPos
            for item in self.items:
                item.moveBy(change.x(), change.y())
    
            super().mouseReleaseEvent(e)
    
    
    if __name__ == "__main__":
    
        app = QApplication(sys.argv)
    
        view = QGraphicsView()
        view.setDragMode(QGraphicsView.RubberBandDrag)
    
        scene = DiagramScene()
    
        scene.setSceneRect(0, 0, 500, 500)
    
        rect1 = scene.addRect(20, 20, 100, 50)
        rect2 = scene.addRect(80, 80, 100, 50)
        rect3 = scene.addRect(140, 140, 100, 50)
    
        rect1.setFlag(QGraphicsItem.ItemIsSelectable, True)
        rect2.setFlag(QGraphicsItem.ItemIsSelectable, True)
        rect3.setFlag(QGraphicsItem.ItemIsSelectable, True)
    
        view.setScene(scene)
        view.show()
    
        sys.exit(app.exec_())
    
    1 回复  |  直到 8 年前
        1
  •  3
  •   Timo    8 年前

    我没有安装PyQt,但我在常规QT和 QGraphicsRectItem .

    QGraphicsItem 以本地坐标表示。局部坐标中的点(0,0)出现在场景中由 QGraphicsItem::pos() (场景坐标)。

    Q图形矩形项 有点特别,因为我们通常不接触 pos (所以我们将其保留为0,0)并将场景坐标中的一个rect传递给 setRect . QGraphicsRectItem::setRect 基本上设置传递值的边界矩形。所以如果你不打电话 setPos (英寸 onSelectionChange )而且只将场景坐标传递给 你应该没事。

    中的mouseEvents DiagramSelBox 也需要调整。我的方法如下:

    1. mousePress:存储 e.pos (映射到场景)和 self.rect.topLeft() 在里面 self.diffPos 并复制 self.rect.topLeft self.startPos
    2. mouseMove:确保 e、 位置 (映射到场景)和 自身.rect.topLeft() 通过移动保持不变 self.rect 周围(使用 自扩散位置 用于计算)
    3. mouseRelease:按以下项之间的差值移动项目 自身.rect.topLeft() 自启动位置 .

    希望这能帮助你开始。