0

Hello to all dear professors! I made the following program for writing with a pen. When the size of window is 900x600,the pen writes at the coordinate point of the mouse this is correct, but when I large the program window, the pen writes farther from the mouse cursor point. In general, why can't we draw at mouse click point when I add the pixmap to the label?

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtCore import Qt


class MainWindow(QtWidgets.QMainWindow):

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

        self.label = QtWidgets.QLabel()
        canvas = QtGui.QPixmap(900, 600)
        canvas.fill(Qt.white)
        self.label.setPixmap(canvas)
        self.setCentralWidget(self.label)

        self.last_x, self.last_y = None, None

    def mouseMoveEvent(self, e):
        if self.last_x is None: # First event.
            self.last_x = e.x()
            self.last_y = e.y()
            return # Ignore the first time.

        painter = QtGui.QPainter(self.label.pixmap())
        painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
        painter.end()
        self.update()

        # Update the origin for next time.
        self.last_x = e.x()
        self.last_y = e.y()

    def mouseReleaseEvent(self, e):
        self.last_x = None
        self.last_y = None


app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
  • It seems pretty obvious that the mouse-events are relative to the main-window, not the pixmap (which has a fixed size). – ekhumoro Dec 05 '21 at 17:07

1 Answers1

0

The alignment() property documentation of QLabel explains it:

By default, the contents of the label are left-aligned and vertically-centered.

In any case, even ignoring the alignment, any mouse based drawing should be done in widget coordinates, while you're trying to do it using the coordinates of the parent.

A better approach should use a subclass of QLabel, using the following implementation:

class MyLabel(QtWidgets.QLabel):
    def __init__(self):
        super().__init__()
        canvas = QtGui.QPixmap(900, 600)
        canvas.fill(Qt.white)
        self.setPixmap(canvas)
        self.last_x, self.last_y = None, None
        self.setAlignment(QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)

    def mouseMoveEvent(self, e):
        if self.last_x is None: # First event.
            self.last_x = e.x()
            self.last_y = e.y()
            return # Ignore the first time.

        painter = QtGui.QPainter(self.pixmap())
        painter.drawLine(self.last_x, self.last_y, e.x(), e.y())
        painter.end()
        self.update()

        # Update the origin for next time.
        self.last_x = e.x()
        self.last_y = e.y()

    def mouseReleaseEvent(self, e):
        self.last_x = None
        self.last_y = None

class MainWindow(QtWidgets.QMainWindow):

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

        self.label = MyLabel()
        self.setCentralWidget(self.label)

Also, see this related question: Mouse position on mouse move event is set on parent instead of child.

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • @AmanullahAmini you're welcome. Please click the gray tick mark on the left of the answer if it solves your problem, in order to make it as accepted. – musicamante Dec 07 '21 at 00:03