我试图以两种方式绘制一条由线组成的路径:第一种,路径由直线组成,它们的末端是共同的。使用这种方法的问题是线条在其末端重叠,从而导致不良影响,如下图所示:
这是代码:
from PyQt5 import QtWidgets, QtCore, QtGui
import typing
import random
class Track(QtWidgets.QGraphicsPathItem):
def __init__(self, parent=None, offset: float = 50):
super(Track, self).__init__(parent) # initiate the parent class
self.__points: list = [QtCore.QPointF(0, 0)]
self.__pen: QtGui.QPen = QtGui.QPen()
self.setPen()
def getPoints(self) -> list:
return self.__points
def append(self, point: QtCore.QPointF):
self.__points.append(point)
def getPen(self) -> QtGui.QPen:
return self.__pen
def setPen(self, pen: QtGui.QPen = None, width: int = 10, color: QtGui.QColor = QtGui.QColor(0, 24, 128, 100),
cap: QtCore.Qt.PenCapStyle = QtCore.Qt.SquareCap, line_style: QtCore.Qt.PenStyle = QtCore.Qt.SolidLine,
join: QtCore.Qt.PenJoinStyle = QtCore.Qt.RoundJoin) -> None:
"""
Set the pen that will be used to paint the implement.
:param pen : set the pen or its arguments
:param width: the pen width.
:param color: the pen color.
:param cap: the cap style: rounded, flatted and squared.
:param line_style: dashed, solid ...
:param join: miter , rounded ...
:return: None
"""
if pen == None:
self.__pen.setWidth(width) # set the pen width
self.__pen.setColor(color) # define your color from QtCore, it is safer to use the statement:
self.__pen.setCapStyle(cap) # set the cap style of the line
self.__pen.setStyle(line_style) # set the line style for instance: solid, dash... whatever
self.__pen.setJoinStyle(join) # set how the lines will be connected.
else:
self.__pen = pen
def paint(self, painter: QtGui.QPainter, option: QtWidgets.QStyleOptionGraphicsItem,
widget: typing.Optional[QtWidgets.QWidget] = ...) -> None:
painter.setPen(self.getPen())
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
try:
path = QtGui.QPainterPath()
path.moveTo(self.getPoints()[0])
for point in self.getPoints():
path.lineTo(point)
painter.drawPath(path)
except IndexError:
self.append(QtCore.QPointF(0, 0))
class Producer(QtCore.QObject):
def __init__(self, parent=None):
super(Producer, self).__init__(parent)
self.__last_point = QtCore.QPointF(10, 0)
self.__point = QtCore.QPointF(10, 0)
self.upper = 10
self.bottom = 0
def setPoint(self) -> None:
self.setLastpoint(self.getPoint())
x = random.randint(self.bottom, self.upper)
y = random.randint(self.bottom, self.upper)
self.upper += 50 # increases the range of probability at the upper limit
self.__point = QtCore.QPointF(x, y) # produce a new random point
def getPoint(self) -> QtCore.QPointF:
return self.__point
def setLastpoint(self, point: QtCore.QPointF):
self.__last_point = point
def getLastPoint(self) -> QtCore.QPointF:
return self.__last_point
class Window2(QtWidgets.QMainWindow):
def __init__(self):
super(Window2, self).__init__()
central_widget = QtWidgets.QWidget()
self.__pen = QtGui.QPen()
self.setMinimumHeight(500)
self.setMinimumWidth(500)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
self.view.setSceneRect(self.view.mapToScene(self.view.viewport().rect()).boundingRect())
self.btn = QtWidgets.QPushButton('Get Track')
self.btn.clicked.connect(self.getTrack)
self.producer = Producer()
hbox = QtWidgets.QHBoxLayout(central_widget)
hbox.addWidget(self.view)
hbox.addWidget(self.btn)
self.setCentralWidget(central_widget)
self.setPen()
def getPen(self) -> QtGui.QPen:
return self.__pen
def getTrack(self):
print('run')
self.producer.setPoint()
line = QtCore.QLineF(self.producer.getPoint(), self.producer.getLastPoint())
self.scene.addLine(line, pen = self.getPen())
dx = self.producer.getPoint().x() - self.producer.getLastPoint().x()
dy = self.producer.getPoint().y() - self.producer.getLastPoint().y()
print(dx, dy)
self.view.setSceneRect(self.view.sceneRect().translated(dx, dy))
def setPen(self, pen: QtGui.QPen = None, width: int = 10, color: QtGui.QColor = QtGui.QColor(0, 24, 128, 100),
cap: QtCore.Qt.PenCapStyle = QtCore.Qt.SquareCap, line_style: QtCore.Qt.PenStyle = QtCore.Qt.SolidLine,
join: QtCore.Qt.PenJoinStyle = QtCore.Qt.RoundJoin) -> None:
"""
Set the pen that will be used to paint the implement.
:param pen : set the pen or its arguments
:param width: the pen width.
:param color: the pen color.
:param cap: the cap style: rounded, flatted and squared.
:param line_style: dashed, solid ...
:param join: miter , rounded ...
:return: None
"""
if pen == None:
self.__pen.setWidth(width) # set the pen width
self.__pen.setColor(color) # define your color from QtCore, it is safer to use the statement:
self.__pen.setCapStyle(cap) # set the cap style of the line
self.__pen.setStyle(line_style) # set the line style for instance: solid, dash... whatever
self.__pen.setJoinStyle(join) # set how the lines will be connected.
else:
self.__pen = pen
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
# w = Window()
w = Window2()
w.show()
sys.exit(app.exec_())
我使用的第二种方法是创建一条由点组成的连续路径。此路径继承类:QGraphicsPathItem。但是,当我“更新”我的“场景矩形”时,当它的一端位于我的边界 =“场景矩形”之外时,这条路径就会消失。有什么办法可以防止它消失吗?我正在采取的这种方法的第二个问题是,我需要保存构成我的路径的这些点......对于少量点这不是问题,但随着我的路径充满点它会有内存管理问题。图片:
代码在这里:
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window, self).__init__()
central_widget = QtWidgets.QWidget()
self.setMinimumHeight(500)
self.setMinimumWidth(500)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
self.view.setSceneRect(self.view.mapToScene(self.view.viewport().rect()).boundingRect())
self.btn = QtWidgets.QPushButton('Get Track')
self.btn.clicked.connect(self.getTrack)
self.producer = Producer()
hbox = QtWidgets.QHBoxLayout(central_widget)
hbox.addWidget(self.view)
hbox.addWidget(self.btn)
self.track = Track()
self.scene.addItem(self.track)
self.setCentralWidget(central_widget)
def getTrack(self):
self.producer.setPoint()
self.track.append(self.producer.getPoint())
dx = self.producer.getPoint().x() - self.producer.getLastPoint().x()
dy = self.producer.getPoint().y() - self.producer.getLastPoint().y()
print(dx, dy)
self.view.setSceneRect(self.view.sceneRect().translated(dx, dy))
我正在托盘模拟 GPS,我正在托盘绘制的路径是汽车的位移。但我不知道这两种方法中哪一种更好,以及是否还有另一种方法。
这是一个最小的可重现示例:
from PyQt5 import QtWidgets, QtCore, QtGui
import typing
import random
pen = QtGui.QPen()
pen.setColor(QtGui.QColor(0, 24, 128, 100))
pen.setWidth(10)
pen.setStyle(QtCore.Qt.SolidLine)
pen.setCapStyle(QtCore.Qt.SquareCap)
class Track(QtWidgets.QGraphicsPathItem):
def __init__(self, parent=None, offset: float = 50):
super(Track, self).__init__(parent) # initiate the parent class
self.__points: list = [QtCore.QPointF(0, 0)]
def getPoints(self) -> list:
return self.__points
def append(self, point: QtCore.QPointF):
self.__points.append(point)
def paint(self, painter: QtGui.QPainter, option: QtWidgets.QStyleOptionGraphicsItem,
widget: typing.Optional[QtWidgets.QWidget] = ...) -> None:
painter.setPen(pen)
painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing)
path = QtGui.QPainterPath()
path.moveTo(self.getPoints()[0])
for point in self.getPoints():
path.lineTo(point)
painter.drawPath(path)
class Producer(QtCore.QObject):
def __init__(self, parent=None):
super(Producer, self).__init__(parent)
self.__last_point = QtCore.QPointF(10, 0)
self.__point = QtCore.QPointF(10, 0)
self.upper = 10
def setPoint(self) -> None:
self.setLastpoint(self.getPoint())
x = random.randint(0, self.upper)
y = random.randint(0, self.upper)
self.upper += 50 # increases the range of probability at the upper limit
self.__point = QtCore.QPointF(x, y) # produce a new random point
def getPoint(self) -> QtCore.QPointF:
return self.__point
def setLastpoint(self, point: QtCore.QPointF):
self.__last_point = point
def getLastPoint(self) -> QtCore.QPointF:
return self.__last_point
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window, self).__init__()
central_widget = QtWidgets.QWidget()
self.setMinimumHeight(500)
self.setMinimumWidth(500)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
self.view.setSceneRect(self.view.mapToScene(self.view.viewport().rect()).boundingRect())
self.btn = QtWidgets.QPushButton('Get Track')
self.btn.clicked.connect(self.getTrack)
self.producer = Producer()
hbox = QtWidgets.QHBoxLayout(central_widget)
hbox.addWidget(self.view)
hbox.addWidget(self.btn)
self.track = Track()
self.scene.addItem(self.track)
self.setCentralWidget(central_widget)
def getTrack(self):
self.producer.setPoint()
self.track.append(self.producer.getPoint())
dx = self.producer.getPoint().x() - self.producer.getLastPoint().x()
dy = self.producer.getPoint().y() - self.producer.getLastPoint().y()
self.view.setSceneRect(self.view.sceneRect().translated(dx, dy))
class Window2(QtWidgets.QMainWindow):
def __init__(self):
super(Window2, self).__init__()
central_widget = QtWidgets.QWidget()
self.setMinimumHeight(500)
self.setMinimumWidth(500)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
self.view.setSceneRect(self.view.mapToScene(self.view.viewport().rect()).boundingRect())
self.btn = QtWidgets.QPushButton('Get Track')
self.btn.clicked.connect(self.getTrack)
self.producer = Producer()
hbox = QtWidgets.QHBoxLayout(central_widget)
hbox.addWidget(self.view)
hbox.addWidget(self.btn)
self.setCentralWidget(central_widget)
def getTrack(self):
self.producer.setPoint()
self.scene.addLine(QtCore.QLineF(self.producer.getPoint(), self.producer.getLastPoint()), pen=pen)
dx = self.producer.getPoint().x() - self.producer.getLastPoint().x()
dy = self.producer.getPoint().y() - self.producer.getLastPoint().y()
self.view.setSceneRect(self.view.sceneRect().translated(dx, dy))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
# w = Window()
w = Window2()
w.show()
sys.exit(app.exec_())