Drawing straight line between two points using QPainterPath

杀马特。学长 韩版系。学妹 提交于 2021-02-17 06:05:41

问题


I have a scene where I would like to draw a line between two points(mouse press should be the start point and mouse release as the endpoint) using the QPainterpath.

Here is a demonstration of how I want it to be.

Here is what's happening with my current code.

Below is the code I have tried

import sys
from PyQt5 import QtWidgets, QtCore, QtGui

class Scene(QtWidgets.QGraphicsScene):

    def __init__(self, *args, **kwargs):
        super(Scene, self).__init__(*args, **kwargs)
        self.point = QtCore.QPointF(0.0, 0.0)

        self.path = QtGui.QPainterPath()

        self.start_point = None
        self.end_point = None

        self.start = False

    def mousePressEvent(self, event):

        self.start_point = event.scenePos()
        self.start = True
        self.path = QtGui.QPainterPath(self.start_point)
        # self.addLine(self.line.setP1(self.start_point))

        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):

        if self.start:
            self.path.lineTo(event.scenePos())
            # self.path.moveTo(event.scenePos())
            self.addPath(self.path, QtGui.QPen(QtCore.Qt.red))

        super(Scene, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):

        if self.start:
            print(self.path)
            self.path.lineTo(event.scenePos())
            # self.path.moveTo(event.scenePos())
            self.addPath(self.path, QtGui.QPen(QtCore.Qt.red))
            self.start = False

        super(Scene, self).mouseReleaseEvent(event)

def main():
    app = QtWidgets.QApplication(sys.argv)

    view = QtWidgets.QGraphicsView()
    view.setRenderHint(QtGui.QPainter.Antialiasing)

    view.setMouseTracking(True)
    scene = Scene()

    view.setScene(scene)
    view.show()
    
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

回答1:


Every time lineTo is used then a new line is created where the starting point is the last point added and the end point is the one that is passed to the function, so you see the curves since they are the union of those lines. The solution is to have 2 variables that store the start point and the end point, and be updated when necessary, then use that information to update the QGraphicsPathItem, not the QPainterPath. The same concept can be applied for QGraphicsLineItem with QLineF.

class Scene(QtWidgets.QGraphicsScene):
    def __init__(self, *args, **kwargs):
        super(Scene, self).__init__(*args, **kwargs)

        self.path_item = self.addPath(QtGui.QPainterPath())

        self.start_point = QtCore.QPointF()
        self.end_point = QtCore.QPointF()

    def mousePressEvent(self, event):
        self.start_point = event.scenePos()
        self.end_point = self.start_point
        self.update_path()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            self.end_point = event.scenePos()
            self.update_path()
        super(Scene, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        self.end_point = event.scenePos()
        self.update_path()
        super(Scene, self).mouseReleaseEvent(event)

    def update_path(self):
        if not self.start_point.isNull() and not self.end_point.isNull():
            path = QtGui.QPainterPath()
            path.moveTo(self.start_point)
            path.lineTo(self.end_point)
            self.path_item.setPath(path)



回答2:


Thx to @eyllanesc for anyone trying to achieve this using QLineF and QGraphicsLineItem here is the code.

import sys
from PyQt5 import QtWidgets, QtCore, QtGui


class Scene(QtWidgets.QGraphicsScene):
    def __init__(self, *args, **kwargs):
        super(Scene, self).__init__(*args, **kwargs)

        self.setSceneRect(QtCore.QRectF(0, 0, 500, 500))

        self.line = None
        self.graphics_line = None

        self.start_point = QtCore.QPointF()
        self.end_point = QtCore.QPointF()

    def mousePressEvent(self, event):
        self.start_point = event.scenePos()
        self.end_point = self.start_point

        self.line = QtCore.QLineF(self.start_point, self.end_point)
        self.graphics_line = QtWidgets.QGraphicsLineItem(self.line)

        self.update_path()
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            self.end_point = event.scenePos()
            self.update_path()
        super(Scene, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        self.end_point = event.scenePos()
        self.update_path()

        super(Scene, self).mouseReleaseEvent(event)

    def update_path(self):
        if not self.start_point.isNull() and not self.end_point.isNull():
            self.line.setP2(self.end_point)
            self.graphics_line.setLine(self.line)
            self.addItem(self.graphics_line)


def main():
    app = QtWidgets.QApplication(sys.argv)

    view = QtWidgets.QGraphicsView()
    view.setRenderHint(QtGui.QPainter.Antialiasing)

    view.setMouseTracking(True)
    scene = Scene()

    view.setScene(scene)
    view.show()

    sys.exit(app.exec_())


if __name__ == '__main__':
    main()



来源:https://stackoverflow.com/questions/65790985/drawing-straight-line-between-two-points-using-qpainterpath

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!