ou2105
ou2105

Reputation: 165

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_()

Upvotes: 2

Views: 5059

Answers (2)

sandcountyfrank
sandcountyfrank

Reputation: 113

I don't have the reputation to reply to eyllanesc's solution, but in case others are having issues, the imports were not complete. Here's is eyllanesc's solution with the imports. It will execute without error:

import sys
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import (QLabel, QWidget)
from PyQt5.QtGui import QPainter, QPainterPath
from PyQt5.QtCore import pyqtSignal, QPoint, QSize
from PyQt5.QtWidgets import QApplication


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_())

Upvotes: 0

eyllanesc
eyllanesc

Reputation: 244282

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

Upvotes: 4

Related Questions