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

使用itemChange()约束QGraphicsItem

  •  2
  • zeus300  · 技术社区  · 7 年前

    我正在使用pyqt和Python 3。我想防止Qgraphicsrecitem在用鼠标拖动时穿过Qgraphicscene中的水平轴(y=0)。我使用以下代码(使用height(),因为矩形位于屏幕的上半部分)。请参阅下面的完整代码示例。

    import sys
    from PyQt4.QtCore import Qt, QPointF
    from PyQt4.QtGui import QGraphicsRectItem, QGraphicsLineItem, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
    
    class MyRect(QGraphicsRectItem):
        def __init__(self, w, h):
            super().__init__(0, 0, w, h)
            self.setFlag(QGraphicsItem.ItemIsMovable, True)
            self.setFlag(QGraphicsItem.ItemIsSelectable, True)
            self.setFlag(QGraphicsItem.ItemIsFocusable, True)
            self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
    
        def itemChange(self, change, value):
            if change == QGraphicsItem.ItemPositionChange:
                if self.y() + self.rect().height() > 0:
                    return QPointF(self.x(), -self.rect().height())
            return value
    
    def main():
        # Set up the framework.
        app = QApplication(sys.argv)
        gr_view = QGraphicsView()
        scene = QGraphicsScene()
        scene.setSceneRect(-100, -100, 200, 200)
        gr_view.setScene(scene)
    
        # Add an x-axis
        x_axis = QGraphicsLineItem(-100, 0, 100, 0)
        scene.addItem(x_axis)
    
        # Add the restrained rect.
        rect = MyRect(50, 50)
        rect.setPos(-25, -100) # <--- not clear to me why I have to do this twice to get the 
        rect.setPos(-25, -100) # item positioned. I know it has to do with my itemChanged above...
        scene.addItem(rect)
    
        gr_view.fitInView(0, 0, 200, 200, Qt.KeepAspectRatio)    
        gr_view.show()
        sys.exit(app.exec_())
    
    if __name__ == '__main__':
        main()
    

    原则上,这是可行的,但当我在水平轴(y=0)下方继续拖动鼠标时,矩形会在拖动时在鼠标位置与其在上半平面中的约束位置之间来回闪烁和跳跃。因此,看起来像是拖动首先将其移动到鼠标光标,然后才追溯调整位置。我想调整之前发生的项目是移动(明显)在所有。

    1 回复  |  直到 7 年前
        1
  •  3
  •   titusjan    7 年前

    您使用 self.y() + self.rect().height() > 0 测试项目是否仍在y轴上方。然而 self.y() 指旧/当前位置。你应该用 value.y() 相反

    因此,方法应为:

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemPositionChange:
            if value.y() + self.rect().height() > 0:
                return QPointF(value.x(), -self.rect().height())
        return super().itemChange(change, value) # Call super
    

    注意,我返回 value.x() 如果测试通过并调用 itemChange itemChange Qt documentation )