Search code examples
pythonpyqt5qpainterqmouseevent

How to get precise mouse pointer location/coordinate in PyQt5 QPainter?


I am trying to draw rectangle in real time in pyqt5 Using QPainter class.

The problem here is that visually the mouse pointer location and the start and end points of the rectangle being drawn are obviously not same. Is there a way I can get accurate coordinates of mouse pointer? What did I do wrong here?

My code:

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

import sys

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # self.setMouseTracking(True)
        self.initUi()
        
        self.drawing = False
        self.start_pos_x = 0
        self.start_pos_y = 0
        self.end_pos_x = 0
        self.end_pos_y = 0
        
        
    def initUi(self):
        self.setWindowTitle("Dummy")
        self.setGeometry(0, 0, 900, 600)
        self.show()
    
    def mousePressEvent(self, event):
        if event.button() == Qt.MouseButton.LeftButton:
            self.drawing = True
            self.start_pos_x = event.globalX()
            self.start_pos_y = event.globalY()
            print(event.globalPos(), event.localPos(), event.x(), event.y())
    
    def mouseMoveEvent(self, event):
        if(event.buttons() & Qt.MouseButton.LeftButton) & self.drawing:
            self.end_pos_x = event.globalX()
            self.end_pos_y = event.globalY()
            self.update()
    def mouseReleaseEvent(self, event):
        if event.button() == Qt.MouseButton.LeftButton:
            print(self.start_pos_x, self.start_pos_y, self.end_pos_x, self.end_pos_y)
            print(event.globalPos())
            self.drawing = False
        
        
        
    def paintEvent(self, event):
        if self.drawing:
            canvas = QPainter(self)
            canvas.setPen(Qt.GlobalColor.blue)
            canvas.drawRect(self.start_pos_x, self.start_pos_y, self.end_pos_x, self.end_pos_y)
        
        
    
app = QApplication(sys.argv)

window = MainWindow()

app.exec_()```

Solution

  • You ned to use local coordinates instead of globals (event.globalX, event.globalY). Here is modified code to get coordinates and draw a rectangle:

    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    
    import sys
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super(MainWindow, self).__init__()
            # self.setMouseTracking(True)
            self.initUi()
            
            self.drawing = False
            self.start_pos = QPoint()
            self.end_pos = QPoint()
            
            
        def initUi(self):
            self.setWindowTitle("Dummy")
            self.setGeometry(0, 0, 900, 600)
            self.show()
        
        def mousePressEvent(self, event):
            if event.button() == Qt.MouseButton.LeftButton:
                self.drawing = True
                self.start_pos = event.pos()
        
        def mouseMoveEvent(self, event):
            if(event.buttons() & Qt.MouseButton.LeftButton) & self.drawing:
                self.end_pos = event.pos()
                self.update()
                
        def mouseReleaseEvent(self, event):
            if event.button() == Qt.MouseButton.LeftButton:
                print(self.start_pos.x(), self.start_pos.y(), self.end_pos.x(), self.end_pos.y())
                self.drawing = False
            
        def paintEvent(self, event):
            if self.drawing:
                canvas = QPainter(self)
                canvas.setPen(Qt.blue)
                rect = QRect(self.start_pos, self.end_pos)
                canvas.drawRect(rect)
            
            
        
    app = QApplication(sys.argv)
    
    window = MainWindow()
    
    app.exec_()