我尝试使用PyQt5将两个椭圆与一条线连接起来。为此,稍微改变了使用github的类。而不是PySide,我使用PyQt5。 代码来自此处:https://github.com/PySide/Examples/blob/master/examples/graphicsview/diagramscene/diagramscene.py
class Arrow(QGraphicsLineItem):
def __init__(self, start_item, end_item, parent=None, scene=None):
super(Arrow, self).__init__(parent, scene)
self.arrowHead = QPolygonF()
self.my_start_item = start_item
self.my_end_item = end_item
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.my_color = QtCore.Qt.black
self.setPen(QPen(self.my_color, 2, QtCore.Qt.SolidLine,
QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
def set_color(self, color):
self.my_color = color
def start_item(self):
return self.my_start_item
def end_item(self):
return self.my_end_item
def boundingRect(self):
extra = (self.pen().width() + 20) / 2.0
p1 = self.line().p1()
p2 = self.line().p2()
return QtCore.QRectF(p1, QtCore.QSizeF(p2.x() - p1.x(), p2.y() - p1.y())).normalized().adjusted(-extra, -extra, extra, extra)
def shape(self):
path = super(Arrow, self).shape()
path.addPolygon(self.arrowHead)
return path
def update_position(self):
line = QtCore.QLineF(self.mapFromItem(self.my_start_item, 0, 0), self.mapFromItem(self.my_end_item, 0, 0))
self.setLine(line)
def paint(self, painter, option, widget=None):
if self.my_start_item.collidesWithItem(self.my_end_item):
return
my_start_item = self.my_start_item
my_end_item = self.my_end_item
my_color = self.my_color
my_pen = self.pen()
my_pen.setColor(self.my_color)
arrow_size = 20.0
painter.setPen(my_pen)
painter.setBrush(self.my_color)
center_line = QtCore.QLineF(my_start_item.pos(), my_end_item.pos())
end_polygon = my_end_item.polygon()
p1 = end_polygon.at(0) + my_end_item.pos()
intersect_point = QtCore.QPointF()
for i in end_polygon:
p2 = i + my_end_item.pos()
poly_line = QtCore.QLineF(p1, p2)
intersect_type, intersect_point = poly_line.intersect(center_line)
if intersect_type == QtCore.QLineF.BoundedIntersection:
break
p1 = p2
self.setLine(QtCore.QLineF(intersect_point, my_start_item.pos()))
line = self.line()
angle = math.acos(line.dx() / line.length())
if line.dy() >= 0:
angle = (math.pi * 2.0) - angle
arrow_p1 = line.p1() + QtCore.QPointF(math.sin(angle + math.pi / 3.0) * arrow_size,
math.cos(angle + math.pi / 3) * arrow_size)
arrow_p2 = line.p1() + QtCore.QPointF(math.sin(angle + math.pi - math.pi / 3.0) * arrow_size,
math.cos(angle + math.pi - math.pi / 3.0) * arrow_size)
self.arrowHead.clear()
for point in [line.p1(), arrow_p1, arrow_p2]:
self.arrowHead.append(point)
painter.drawLine(line)
painter.drawPolygon(self.arrowHead)
if self.isSelected():
painter.setPen(QPen(my_color, 1, QtCore.Qt.DashLine))
my_line = QtCore.QLineF(line)
my_line.translate(0, 4.0)
painter.drawLine(my_line)
my_line.translate(0, -8.0)
painter.drawLine(my_line)
创建箭头
arrow = Arrow(start, end, scene=scene)
scene.addItem(arrow)
arrow.update_position()
运行代码时出现错误
答案 0 :(得分:1)
PyQt5是由riverbankcomputing公司创建的Qt5的包装器,而PySide是由当时Qt的创建者创建的Qt4的包装器。除了Qt4和Qt5有很多不同之处,所以这些库根本不兼容,例如在你的情况下PySide项你可以将场景作为参数传递,但在PyQt4或PyQt5的情况下,这个参数是不必要的:
<强> PySide:强>
class PySide.QtGui.QGraphicsLineItem([parent = None [,scene = None]])
class PySide.QtGui.QGraphicsLineItem(line [,parent = None [,scene = None]])
class PySide.QtGui.QGraphicsLineItem(x1,y1,x2,y2 [,parent = None [,scene = None]])
<强> PyQt5:强>
QGraphicsLineItem(parent:QGraphicsItem = None)
QGraphicsLineItem(QLineF,parent:QGraphicsItem = None)
QGraphicsLineItem(float,float,float,float,parent:QGraphicsItem = None)
除了这些差别是类Signal()
和pyqtSignal
之外,显然从Qt4到Qt5的步骤假设将一些属于QtGui的类分离为QtWidgets。
您的案例中的解决方案是消除场景参数,因为它会发生变化:
class Arrow(QGraphicsLineItem):
def __init__(self, start_item, end_item, parent=None, scene=None):
super(Arrow, self).__init__(parent, scene)
为:
class Arrow(QGraphicsLineItem):
def __init__(self, start_item, end_item, parent=None):
super(Arrow, self).__init__(parent)
我已将该项目翻译为PyQt5,您可以在以下link中查看。