When moving the scroll, the circles are drawn not centered.

import sys from PyQt5.QtWidgets import QVBoxLayout, QWidget, QApplication, QLabel, QHBoxLayout, QScrollArea from PyQt5.QtGui import QPainter, QColor, QMouseEvent, QImage, QPixmap, QPalette from PyQt5.QtCore import Qt, QPoint class Example(QWidget): def __init__(self): super().__init__() self.flag = False self.initUI() def initUI(self): self.resize(500, 500) self.image = QImage(self.width(), self.height(), QImage.Format_ARGB32) self.image.fill(QColor(255, 255, 255)) self.hbox = QHBoxLayout() self.label = QLabel() self.label.setAlignment(Qt.AlignLeft) scroll = QScrollArea() self.valueWidth = scroll.verticalScrollBar().value() scroll.setBackgroundRole(QPalette.Dark) self.label.setGeometry(10, 10, 500, 500) self.label.setPixmap(QPixmap.fromImage(self.image)) scroll.setWidget(self.label) self.hbox.addWidget(scroll) self.setLayout(self.hbox) self.show() def mousePressEvent(self, e): if e.button() != Qt.LeftButton: self.flag = False if e.button() == Qt.LeftButton: self.flag = True self.paint = QPainter(self.image) self.ellips(e) def paintEvent(self, e): paint = QPainter(self) self.label.setPixmap(QPixmap.fromImage(self.image)) def mouseMoveEvent(self, e): if self.flag: print(e.pos()) self.ellips(e) def ellips(self,e): self.paint.setBrush(QColor('yellow')) self.paint.drawEllipse(e.pos() - QPoint(10, 10), 20, 20) self.update() app = QApplication(sys.argv) w = Example() sys.exit(app.exec_()) 
  • The code in question is invalid, please correct. - gil9red
  • @ gil9red corrected - Daniil
  • Recommendations: 1) indent between methods, difficult to understand in your mash 2) change the size and position of a window by its constructor 3) group the code by meaning or object, for example, it makes sense to do all actions with the label in a row rather than smearing it by the designer - gil9red

1 answer 1

The problem was that they tracked the position of the cursor on the widget, and painted on his child, and because the child was on the scrollArea, only part of it could be seen.

In this example, I rewrote the code so that mouse movement is tracked directly on the child:

 from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QHBoxLayout, QScrollArea, QMessageBox from PyQt5.QtGui import QPainter, QColor, QPixmap, QPalette from PyQt5.QtCore import Qt, QEvent def log_uncaught_exceptions(ex_cls, ex, tb): text = '{}: {}:\n'.format(ex_cls.__name__, ex) import traceback text += ''.join(traceback.format_tb(tb)) print(text) QMessageBox.critical(None, 'Error', text) quit() import sys sys.excepthook = log_uncaught_exceptions class Example(QWidget): def __init__(self): super().__init__() self.flag = False self.image = QPixmap('image.jpg') self.label = QLabel() self.label.setAlignment(Qt.AlignLeft) self.label.setPixmap(self.image) # Установка Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° событий self.label.installEventFilter(self) self.scroll_area = QScrollArea() self.scroll_area.setBackgroundRole(QPalette.Dark) self.scroll_area.setWidget(self.label) layout = QHBoxLayout() layout.addWidget(self.scroll_area) self.setLayout(layout) # Π ΠΈΡΠΎΠ²Π°Ρ‚ΡŒ Π±ΡƒΠ΄Π΅ΠΌ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ΅ self.painter = QPainter(self.image) self.painter.setBrush(QColor('yellow')) def eventFilter(self, obj, e): # Если событиС ΠΏΡ€ΠΈΡˆΠ»ΠΎ ΠΎΡ‚ self.label if obj == self.label: # Если событиС наТатия ΠΊΠ½ΠΎΠΏΠΊΠΈ ΠΌΡ‹ΡˆΠΊΠΈ ΠΈ Π·Π°ΠΆΠ°Ρ‚Π° лСвая ΠΊΠ½ΠΎΠΏΠΊΠ° if e.type() == QEvent.MouseButtonPress and e.button() == Qt.LeftButton: self.flag = True self.draw_ellipse(e) # Если событиС отпускания ΠΊΠ½ΠΎΠΏΠΊΠΈ ΠΌΡ‹ΡˆΠΊΠΈ ΠΈ Π·Π°ΠΆΠ°Ρ‚Π° лСвая ΠΊΠ½ΠΎΠΏΠΊΠ° elif e.type() == QEvent.MouseButtonRelease and e.button() == Qt.LeftButton: self.flag = False # Если событиС двиТСния ΠΌΡ‹ΡˆΠΊΠΈ ΠΈ Π·Π°ΠΆΠ°Ρ‚Π° лСвая ΠΊΠ½ΠΎΠΏΠΊΠ° elif e.type() == QEvent.MouseMove and self.flag: self.draw_ellipse(e) # Бтандартная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° событий return super().eventFilter(obj, e) def draw_ellipse(self, e): self.painter.drawEllipse(e.pos(), 20, 20) self.label.setPixmap(self.image) if __name__ == '__main__': app = QApplication([]) w = Example() w.resize(500, 500) w.show() app.exec() 

Screenshot:

enter image description here