提问人:Djodjo Badibanga 提问时间:11/13/2023 更新时间:11/13/2023 访问量:19
绘制任意线条以连接两个项目并移动它们 PyQt5
draw any lines to connect two items and move them PyQt5
问:
根据此页面中的代码,我冒昧地根据自己的需要对其进行了调整,但现在我被卡住了。我添加了从按钮创建正方形的功能,还更改了点的位置,使它们不仅在一侧,而且在上方和下方。
现在我的问题是我无法在其中一个点上封线。当我创建线并在两个项目上连接两个点时,一旦我移动其中一个项目甚至两个项目,连接就会发生变化。如果该线连接到下面的点,则它将更改为连接到上面的点。无论移动如何,我都想密封链接。
谢谢你的帮助。
`import sys
from PyQt5 import QtWidgets, QtCore, QtGui
class CustomItem(QtWidgets.QGraphicsItem):
def __init__(self, pointONLeft=False, *args, **kwargs):
super().__init__(*args, **kwargs)
self.ellipseOnLeft = pointONLeft
self.point = None
self.endPoint = None
self.isStart = None
self.line = None
self.setAcceptHoverEvents(True)
self.setFlag(self.ItemIsMovable)
self.setFlag(self.ItemSendsGeometryChanges)
self.lines = []
def addLine(self, line, isStart):
self.lines.append((line, isStart))
def itemChange(self, change, value):
if change == self.ItemPositionChange and self.scene():
self.moveLineToCenter(value)
return super(CustomItem, self).itemChange(change, value)
def moveLineToCenter(self, newPos):
for line, isStart in self.lines:
xOffset = 50
yOffsetStart = -5
yOffsetEnd = 105
yOffset = yOffsetStart if isStart else yOffsetEnd
newCenterPos = QtCore.QPointF(newPos.x() + xOffset, newPos.y() + yOffset)
p1 = newCenterPos if isStart else line.line().p1()
p2 = line.line().p2() if isStart else newCenterPos
line.setLine(QtCore.QLineF(p1, p2))
def containsPoint(self, pos):
topEllipse = self.mapToScene(QtCore.QRectF(45, -5, 10, 10).adjusted(-0.5, -0.5, 0.5, 0.5))
bottomEllipse = self.mapToScene(QtCore.QRectF(45, 95, 10, 10).adjusted(-0.5, -0.5, 0.5, 0.5))
if topEllipse.containsPoint(pos, QtCore.Qt.OddEvenFill):
return "top"
elif bottomEllipse.containsPoint(pos, QtCore.Qt.OddEvenFill):
return "bottom"
else:
return None
def boundingRect(self):
return QtCore.QRectF(-5, 0, 110, 110)
def paint(self, painter, option, widget):
pen = QtGui.QPen(QtCore.Qt.red)
pen.setWidth(2)
painter.setPen(pen)
painter.setBrush(QtGui.QBrush(QtGui.QColor(31, 176, 224)))
painter.drawRoundedRect(QtCore.QRectF(0, 0, 100, 100), 4, 4)
painter.setBrush(QtGui.QBrush(QtGui.QColor(214, 13, 36)))
painter.drawEllipse(QtCore.QRectF(45, -5, 10, 10))
painter.drawEllipse(QtCore.QRectF(45, 95, 10, 10))
def containsPoint(self, pos):
topEllipse = self.mapToScene(QtCore.QRectF(45, -5, 10, 10).adjusted(-0.5, -0.5, 0.5, 0.5))
bottomEllipse = self.mapToScene(QtCore.QRectF(45, 95, 10, 10).adjusted(-0.5, -0.5, 0.5, 0.5))
return topEllipse.containsPoint(pos, QtCore.Qt.OddEvenFill) or bottomEllipse.containsPoint(pos, QtCore.Qt.OddEvenFill)
class Scene(QtWidgets.QGraphicsScene):
def __init__(self, *args, **kwargs):
super(Scene, self).__init__(*args, **kwargs)
self.startPoint = None
self.endPoint = None
self.line = None
self.graphics_line = None
self.item1 = None
self.item2 = None
self.isStart = None
def mousePressEvent(self, event):
self.line = None
self.graphics_line = None
self.item1 = None
self.item2 = None
self.startPoint = None
self.endPoint = None
if self.itemAt(event.scenePos(), QtGui.QTransform()) and isinstance(self.itemAt(event.scenePos(), QtGui.QTransform()), CustomItem):
self.item1 = self.itemAt(event.scenePos(), QtGui.QTransform())
self.checkPoint1(event.scenePos())
if self.startPoint:
self.line = QtCore.QLineF(self.startPoint, self.endPoint)
self.graphics_line = self.addLine(self.line)
self.update_path()
super(Scene, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() & QtCore.Qt.LeftButton and self.startPoint:
self.endPoint = event.scenePos()
self.update_path()
super(Scene, self).mouseMoveEvent(event)
def filterCollidingItems(self, items): # filters out all the colliding items and returns only instances of CustomItem
return [x for x in items if isinstance(x, CustomItem) and x != self.item1]
def mouseReleaseEvent(self, event):
if self.graphics_line:
self.checkPoint2(event.scenePos())
self.update_path()
if self.item2:
self.item1.addLine(self.graphics_line, True)
self.item2.addLine(self.graphics_line, False)
else:
self.removeItem(self.graphics_line)
self.graphics_line = None
super(Scene, self).mouseReleaseEvent(event)
def checkPoint1(self, pos):
if self.item1.containsPoint(pos):
self.item1.setFlag(self.item1.ItemIsMovable, False)
self.startPoint = self.endPoint = pos
else:
self.item1.setFlag(self.item1.ItemIsMovable, True)
def checkPoint2(self, pos):
item_lst = self.filterCollidingItems(self.graphics_line.collidingItems())
contains = False
if not item_lst: # checks if there are any items in the list
return
for self.item2 in item_lst:
if self.item2.containsPoint(pos):
contains = True
self.endPoint = pos
break
if not contains:
self.item2 = None
def update_path(self):
if self.startPoint and self.endPoint:
self.line.setP2(self.endPoint)
self.graphics_line.setLine(self.line)
if self.item1:
self.item1.moveLineToCenter(self.item1.pos())
def main():
app = QtWidgets.QApplication(sys.argv)
scene = Scene()
mainWindow = QtWidgets.QMainWindow()
mainWindow.setWindowTitle("Créateur de carrés")
mainWindow.resize(800, 600)
view = QtWidgets.QGraphicsView(scene)
view.setViewportUpdateMode(view.FullViewportUpdate)
view.setMouseTracking(True)
mainWindow.setCentralWidget(view)
menuBar = mainWindow.menuBar()
fileMenu = menuBar.addMenu("&File")
createAction = QtWidgets.QAction("&Créer Carré", mainWindow)
createAction.triggered.connect(lambda: createSquare(scene))
fileMenu.addAction(createAction)
mainWindow.show()
sys.exit(app.exec_())
def createSquare(scene):
item = CustomItem()
scene.addItem(item)
item.setPos(QtCore.QPointF(50, 50))
if __name__ == '__main__':
main()`
答: 暂无答案
上一个:如何删除 github 自述文件配置文件中的这些“行”
下一个:正确绘制线数据
评论