PyQt - 是否有将 QGraphicsItem 移动限制到特定线路路径的实现?
PyQt - Is there an implementation to constrain QGraphicsItem movement to a certain line path?
我试图通过在移动矩形鼠标时使矩形项目的原点跟随此 QGraphicsLineItem
来限制此 QGraphicsRectItem
的移动。
有什么方法可以做到吗?
我通过创建修改后的矩形项目和订单项,通过简单的实现获得了它:
class Rectangle(QGraphicsRectItem):
def __init__(self, x=0, y=0, w=0, h=0, pathes=[]):
super(Rectangle, self).__init__(x, y, w, h) # x, y are internal object coordinates
self.setTransformOriginPoint(int(w / 2), int(h / 2)) # setting the origin point to the middle
self.origin = self.transformOriginPoint() # returns QPointF
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges)
self.pathes = pathes
def item_on_path(self, new_point):
new_point = QPointF(new_point.x() + self.origin.x(), new_point.y() + self.origin.y())
for path in self.pathes:
if path.contains(new_point):
return True
return False
class Line(QGraphicsLineItem):
def __init__(self, pt1, pt2):
super(Line, self).__init__(pt1[0], pt1[1], pt2[0], pt2[1])
然后用QShortcut
创建场景对象进行键盘控制并设置场景:
class graphicsViewObject(QGraphicsView):
def __init__(self):
super(graphicsViewObject, self).__init__()
self.scene = QGraphicsScene()
black_pen = QPen(Qt.black)
black_pen.setWidth(5)
self.setScene(self.scene)
self.speed = 10 # keyboard movement change value
pt1 = (200, 200)
pt2 = (800, 200)
self.line_1 = Line(pt1, pt2)
self.line_1.setPen(black_pen)
self.scene.addItem(self.line_1)
self.rect = Rectangle(w=200, h=200, pathes=[self.line_1])
self.rect.setPen(black_pen)
self.rect.setBrush(QBrush(Qt.red))
self.scene.addItem(self.rect)
# Moving the rectangle origin to the first point of the line
self.rect.setPos(QPointF(pt1[0] - self.rect.origin.x(), pt1[1] - self.rect.origin.y()))
QShortcut(Qt.Key_Up, self, self.fooUp)
QShortcut(Qt.Key_Down, self, self.fooDown)
QShortcut(Qt.Key_Left, self, self.fooLeft)
QShortcut(Qt.Key_Right, self, self.fooRight)
def fooUp(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setY(pos.y() - self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
def fooDown(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setY(pos.y() + self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
def fooLeft(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setX(pos.x() - self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
def fooRight(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setX(pos.x() + self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
我试图通过在移动矩形鼠标时使矩形项目的原点跟随此 QGraphicsLineItem
来限制此 QGraphicsRectItem
的移动。
有什么方法可以做到吗?
我通过创建修改后的矩形项目和订单项,通过简单的实现获得了它:
class Rectangle(QGraphicsRectItem):
def __init__(self, x=0, y=0, w=0, h=0, pathes=[]):
super(Rectangle, self).__init__(x, y, w, h) # x, y are internal object coordinates
self.setTransformOriginPoint(int(w / 2), int(h / 2)) # setting the origin point to the middle
self.origin = self.transformOriginPoint() # returns QPointF
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges)
self.pathes = pathes
def item_on_path(self, new_point):
new_point = QPointF(new_point.x() + self.origin.x(), new_point.y() + self.origin.y())
for path in self.pathes:
if path.contains(new_point):
return True
return False
class Line(QGraphicsLineItem):
def __init__(self, pt1, pt2):
super(Line, self).__init__(pt1[0], pt1[1], pt2[0], pt2[1])
然后用QShortcut
创建场景对象进行键盘控制并设置场景:
class graphicsViewObject(QGraphicsView):
def __init__(self):
super(graphicsViewObject, self).__init__()
self.scene = QGraphicsScene()
black_pen = QPen(Qt.black)
black_pen.setWidth(5)
self.setScene(self.scene)
self.speed = 10 # keyboard movement change value
pt1 = (200, 200)
pt2 = (800, 200)
self.line_1 = Line(pt1, pt2)
self.line_1.setPen(black_pen)
self.scene.addItem(self.line_1)
self.rect = Rectangle(w=200, h=200, pathes=[self.line_1])
self.rect.setPen(black_pen)
self.rect.setBrush(QBrush(Qt.red))
self.scene.addItem(self.rect)
# Moving the rectangle origin to the first point of the line
self.rect.setPos(QPointF(pt1[0] - self.rect.origin.x(), pt1[1] - self.rect.origin.y()))
QShortcut(Qt.Key_Up, self, self.fooUp)
QShortcut(Qt.Key_Down, self, self.fooDown)
QShortcut(Qt.Key_Left, self, self.fooLeft)
QShortcut(Qt.Key_Right, self, self.fooRight)
def fooUp(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setY(pos.y() - self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
def fooDown(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setY(pos.y() + self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
def fooLeft(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setX(pos.x() - self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)
def fooRight(self):
for item in self.scene.selectedItems():
pos = item.scenePos()
pos.setX(pos.x() + self.speed)
item_inside_scene = self.scene.sceneRect().contains(item.mapRectToScene(item.boundingRect()))
if item.item_on_path(pos) and item_inside_scene:
item.setPos(pos)