Search code examples
pythonpyqtdrawingqgraphicsview

Drawing a line consisting of multiple points using PyQt


I want to draw a line consisting of multiple points via mouse click in a Python script using PyQt. I need all coordinates of the ponts and I want to be able to delete the line. Here's my script doing all the work, except for the graphical line drawing itself, it just prints what it does:

#!/usr/bin/python3

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class endomess(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.draw = False

    def mousePressEvent(self, event):

        if event.button() == Qt.LeftButton:

            if self.draw == False:
                print('Starting to draw at', str(event.pos()))
                self.draw = True
                self.linePoints = []

            elif self.draw == True:
                print('Appending', str(event.pos()))

            self.linePoints.append(event.pos())

        elif event.button() == Qt.RightButton:
            if self.draw == True:
                print('Finished drawing. List of all points:', str(self.linePoints))
                self.draw = False

def main(argv):
    app = QApplication(argv, True)
    wnd = endomess()
    wnd.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main(sys.argv)

So, here's my problem: how do I actually draw that line that can be defined via the above script? I already had a look at scribble.py and some Qt paint docs, but I don't get it. Probably, this is not a problem for someone more experienced with Qt?

Thanks in advance for all help!


Solution

  • You should probably use the graphics view framework for drawing the lines, rather than attempting to paint them directly.

    Here's a basic demo to get you started:

    from PyQt4 import QtGui, QtCore
    
    class Window(QtGui.QWidget):
        def __init__(self):
            QtGui.QWidget.__init__(self)
            self.view = View(self)
            self.button = QtGui.QPushButton('Clear View', self)
            self.button.clicked.connect(self.handleClearView)
            layout = QtGui.QVBoxLayout(self)
            layout.addWidget(self.view)
            layout.addWidget(self.button)
    
        def handleClearView(self):
            self.view.scene().clear()
    
    class View(QtGui.QGraphicsView):
        def __init__(self, parent):
            QtGui.QGraphicsView.__init__(self, parent)
            self.setScene(QtGui.QGraphicsScene(self))
            self.setSceneRect(QtCore.QRectF(self.viewport().rect()))
    
        def mousePressEvent(self, event):
            self._start = event.pos()
    
        def mouseReleaseEvent(self, event):
            start = QtCore.QPointF(self.mapToScene(self._start))
            end = QtCore.QPointF(self.mapToScene(event.pos()))
            self.scene().addItem(
                QtGui.QGraphicsLineItem(QtCore.QLineF(start, end)))
            for point in (start, end):
                text = self.scene().addSimpleText(
                    '(%d, %d)' % (point.x(), point.y()))
                text.setBrush(QtCore.Qt.red)
                text.setPos(point)
    
    if __name__ == '__main__':
    
        import sys
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.resize(640, 480)
        window.show()
        sys.exit(app.exec_())