Search code examples
pythonqtpyqtpyqt5qpainter

PyQt5: painting using events


I am new on PyQt I am working on a project on which I should implement a feature that make the user able to draw a digit using the mouse (digit recognition system). So what I want is when the mouse button is pressed the app will start to draw till the button is released. I made this source code but it is still not working (I think I am struggling with sending a signal to PaintEvent()).

import sys
from PyQt5 import QtCore 
from PyQt5 import QtGui, QtWidgets

from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog,QGraphicsView,QGraphicsScene,QVBoxLayout

from PyQt5.QtWidgets import (QApplication, QLabel, QWidget)
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication



class Communicate(QObject): 
    drawApp = pyqtSignal() 

class MyWidget(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI() 

    def initUI(self):
        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Simple')
        self.setMouseTracking(True)
        self.label = QLabel(self)
        self.label.resize(500, 40)
        self.c = Communicate()
        self.c.drawApp.connect(self.PaintEvent())  

        self.show()


    def mousePressEvent(self, event):

        self.c.drawApp.emit()
        self.startingposx = event.x()
        self.startingposy = event.y()
        #super().mousePressEvent(event)
        print ("mouse pressed")


    def mouseMoveEvent(self, event):

        self.label.setText('Coordinates: ( %d : %d )' % (event.x(), event.y()) )
        self.y = event.y()
        self.x=event.x()  


    def PaintEvent(self,event):

           qp = QPainter()  
           qp.begin(self)

           #qp.setPen(Qt.red)
           qp.drawPoints(self,qp)
           qp.end()

           self.update()



    def mouseReleaseEvent(self,event):
        self.endingposx = event.x()
        self.endingposy = event.y()
        super().mouseReleaseEvent(event)
        print("starting point was",self.startingposx)
        print("starting point y was ",self.startingposy)
        print("ending point was ",self.endingposx)
        print("ending point was y ",self.endingposy)
        print("released")    



    def drawPoints(self,qp):

          qp.setPen(Qt.red)
          size = self.size()
          x=self.x
          y=self.y
          qp.drawPoint(x,y)     

app = QApplication(sys.argv)


widget = MyWidget()

widget.show()

app.exec_()

Solution

  • Python is sensitive to uppercase and lowercase so be more careful, the method is called paintEvent.

    Also you should not call paintEvent directly, you must use the function update(), this method will internally call paintEvent().

    But even correcting that error your problem is not solved, if you want to draw a path it is advisable to use QPainterPath as this stores the strokes.

    class Drawer(QWidget):
        newPoint = pyqtSignal(QPoint)
        def __init__(self, parent=None):
            QWidget.__init__(self, parent)
            self.path = QPainterPath()    
    
        def paintEvent(self, event):
            painter = QPainter(self)
            painter.drawPath(self.path)
    
        def mousePressEvent(self, event):
            self.path.moveTo(event.pos())
            self.update()
    
        def mouseMoveEvent(self, event):
            self.path.lineTo(event.pos())
            self.newPoint.emit(event.pos())
            self.update()
    
        def sizeHint(self):
            return QSize(400, 400)
    
    class MyWidget(QWidget):
        def __init__(self, parent=None):
            QWidget.__init__(self, parent)
            self.setLayout(QVBoxLayout())
            label = QLabel(self)
            drawer = Drawer(self)
            drawer.newPoint.connect(lambda p: label.setText('Coordinates: ( %d : %d )' % (p.x(), p.y())))
            self.layout().addWidget(label)
            self.layout().addWidget(drawer)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = MyWidget()
        w.show()
        sys.exit(app.exec_())
    

    Screenshot:

    enter image description here