0

I'm working on a GUI application and I have a problem with the construction of QRect by mouse tracking within an image.

The issue at hand

In deed, I want to draw a single rectangle on the window by using mouseMoveEvent.

I started to draw on the window itself but it doesn't work.
I also tried to use true coordinates rather than QPoint object but the effect is the same.

The MRE Code example :

class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('Python')

        # setting geometry of window
        self.setGeometry(100, 100, 600, 400)

        #Display layouts
        self.zone_plot = QGridLayout()

        self.center_layout = QVBoxLayout()
        
        #Image creation
        path = '/home/lidaoa/PycharmProjects/stars.jpeg' #path to change
        self.image = QPixmap(path)

        self.image = self.image.scaled(700,500, Qt.KeepAspectRatio, Qt.FastTransformation)

        self.lab_im = QLabel()
        self.lab_im.setPixmap(self.image)
        self.lab_im.adjustSize()
        
        #Events to draw on the image
        self.lab_im.mousePressEvent, self.lab_im.mouseMoveEvent, self.lab_im.mouseReleaseEvent = self.press_zone, self.track_zone, self.release_zone

        self.flag = False
        
        #Initialization of points
        self.begin,self.dest = QPoint(),QPoint()

        self.center_layout.addWidget(self.lab_im,alignment=Qt.AlignCenter)

        self.zone_plot.addLayout(self.center_layout,1,1)

        self.setLayout(self.zone_plot)

        self.show()

    def paintEvent(self,event):
        if not self.flag:
            return None

        qpaint = QPainter(self.lab_im.pixmap())

        qpaint.setPen(QColor(200,0,0))

        qpaint.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform,True)
        if not self.begin.isNull() and not self.dest.isNull():
            rect = QRect(self.begin,self.dest).normalized()
            qpaint.drawRect(rect)

        qpaint.end()
        del qpaint

    def press_zone(self,event):
        self.flag = True
        if event.buttons() & Qt.LeftButton:
            self.begin = event.pos()
            self.dest = self.begin

        self.update()

    def track_zone(self, event):
        if event.buttons() & Qt.LeftButton:
            self.dest =  event.pos()
        self.update()

    def release_zone(self,event):
        if event.buttons() & Qt.LeftButton:
            rect = QRect(self.begin,self.dest).normalized()
            qpaint = QPainter(self.lab_im.pixmap())
            qpaint.drawRect(rect)
            self.begin, self.dest = QPoint(),QPoint()

        self.update()
        self.flag = False

# App creation
App = QApplication(sys.argv)

window = Window()

sys.exit(App.exec())
greybeard
  • 2,249
  • 8
  • 30
  • 66
Lid Al
  • 1
  • 3
  • How are those `press_zone`, `track_zone` and `release_zone` being called? Please provide a valid [mre], but also be aware that if you want to paint on a widget, you should override **its** paint event, not that of the parent. You should also avoid to directly paint on the pixmap of a QLabel (as said, your code is incomplete, but I'm assuming that that's what you're trying to do), but instead get the pixmap, draw into it, and then set it again on the label. – musicamante May 04 '23 at 17:54
  • I use mousePressEvent as press_zone , mouseMoveEvent as track_zone and mouseReleaseEvent as release_zone – Lid Al May 04 '23 at 22:22
  • There's no trace of those in your code (and you should normally avoid to override event handlers with different function names), so, as said, please provide a MRE. – musicamante May 04 '23 at 23:57
  • Okay thanks, I've sent an more precise example below – Lid Al May 05 '23 at 08:31
  • As said, you need to implement the drawing on the target widget (the label), not its parent, and override the `paintEvent()` from there, then call the base paintEvent implementation and draw the rectangle in a *new* QPainter set for the QLabel. See [this related post](https://stackoverflow.com/a/60468111) for an example. – musicamante May 06 '23 at 18:05
  • Hmm, what do you called override "paint event" ? I don't understand clearly what does it mean. And I tried to draw on the QLabel but an error message is shown saying that "QPainter is not active" – Lid Al May 07 '23 at 12:00
  • You got that message because you can only create a QPainter on a widget within **ITS** `paintEvent()`, you can **NOT** create a painter on another widget, so you need to create a subclass of the widget on which you want to paint (QLabel, in this case) and override `paintEvent()` *there*, not in `Window`. See link in my previous comment. If you don't know what override means, please look it up, as you cannot use OOP if you don't know basic terminology. – musicamante May 07 '23 at 18:01
  • Okay, I see better. Sincerely thanks – Lid Al May 08 '23 at 21:37
  • Okay, I finally succeed by defining a new QLabel class. Thanks for your help – Lid Al May 11 '23 at 12:38
  • Why not answer your own question? – relent95 May 22 '23 at 12:03

0 Answers0