Search code examples
pythonpyqt5qpainter

How to draw polyline with PyQt5 in Python?


I want to draw polyline with mouse event. But I can't set endpoints by clicking, or choose pen type. I want to draw linear lines, but when i write this code it only shows dots instead of drawing a line. Here is my code:

import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtGui import QPainter, QBrush, QColor, QPen, QPainterPath
from PyQt5.QtWidgets import QLabel, QGraphicsScene, QGraphicsView


class MyWidget(QtWidgets.QWidget):
def __init__(self):
    super().__init__()
    self.begin = QtCore.QPoint()
    self.end = QtCore.QPoint()
    self.beginList = []
    self.endList = []
    self.initUI()

def initUI(self):
    self.setGeometry(200, 200, 1000, 500)
    self.label = QLabel(self)
    self.label.resize(500, 40)
    self.show()

def paintEvent(self, event):
    qp = QPainter(self)
    for i,j in zip(self.beginList, self.endList):
        qp.drawLines(QtCore.QLineF(i,j))


def mouseMoveEvent(self, event):
    self.begin = event.pos()
    self.end = event.pos()
    self.beginList.append(self.begin)
    self.endList.append(self.end)
    self.label.setText('Coordinates: ( %d : %d )' % (event.x(), event.y()))
    self.update()

def mouseReleaseEvent(self, event):
    self.begin = event.pos()
    self.end = event.pos()

if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWidget()
window.resize(800,600)
sys.exit(app.exec_())

Solution

  • If the OP code is analyzed, the starting point and the end point coincide, so when drawing a line between 2 points of the same location, only one point will be drawn. The logic is to join the point obtained in the i-th step with the (i+1)-th point.

    To do the above the simplest thing is to use a QPainterPath:

    import sys
    from PyQt5 import QtWidgets, QtGui, QtCore
    
    
    class MyWidget(QtWidgets.QWidget):
        def __init__(self):
            super().__init__()
            self.initUI()
            self.paths = []
    
        def initUI(self):
            self.setGeometry(200, 200, 1000, 500)
            self.label = QtWidgets.QLabel(self)
            self.show()
    
        def paintEvent(self, event):
            qp = QtGui.QPainter(self)
            for path in self.paths:
                qp.drawPath(path)
    
        def mousePressEvent(self, event):
            path = QtGui.QPainterPath()
            path.moveTo(event.pos())
            self.paths.append(path)
            super().mousePressEvent(event)
    
        def mouseMoveEvent(self, event):
            self.paths[-1].lineTo(event.pos())
            self.label.setText('Coordinates: ( %d : %d )' % (event.x(), event.y()))
            self.label.adjustSize()
            self.update()
            super().mouseMoveEvent(event)
    
        def mouseReleaseEvent(self, event):
            self.paths[-1].lineTo(event.pos())
            self.update()
            super().mouseReleaseEvent(event)
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        window = MyWidget()
        window.resize(800, 600)
        sys.exit(app.exec_())