pyqt5 QLabel Image setScaledContents (True) не разрешать обновления Qpainter - PullRequest
0 голосов
/ 11 марта 2020

Я хочу отобразить изображение и поставить маркер в текущей позиции мыши для каждого щелчка левой кнопкой мыши.

Однако нижеприведенный код работает, только если прокомментирован ("self.imglabel.setScaledContents(True)"). Любая причина?

Я должен выполнять эту работу на различных изображениях с разным разрешением, я читаю, чтобы поддерживать правильное соотношение сторон и отображать изображение, которое нам необходимо использовать setScaledContents(True). Но почему включение этого не позволяет update() (PaintEvent) ??

import sys
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QSizePolicy, QMessageBox
from PyQt5.QtGui import QPixmap, QPainter, QPen, QColor, QImage, QPalette

class Menu(QMainWindow):
    def __init__(self):
        super().__init__()
        self.central_widget = QWidget()               # define central widget
        self.setCentralWidget(self.central_widget)
        self.vbox = QVBoxLayout(self.central_widget)       
        self.vbox.addWidget(self.imgWidget())
        self.vbox.addWidget(QPushButton("test"))

    def imgWidget(self):
        self.imglabel = QLabel()
        self.imglabel.setScaledContents(True)
        self.image = QImage("calib.jpeg")
        self.imagepix = QPixmap.fromImage(self.image)
        self.imglabel.setPixmap(self.imagepix)
        self.imglabel.mousePressEvent = self.imgMousePress
        return self.imglabel

    def imgMousePress(self, e):
        painter = QPainter(self.imglabel.pixmap())
        pen = QPen()
        pen.setWidth(10)
        pen.setColor(QColor('red'))
        painter.setPen(pen)
        painter.drawPoint(e.x(), e.y())
        painter.end()
        self.imglabel.update()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainMenu = Menu()
    mainMenu.show()
    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 11 марта 2020

Чтобы избежать ненужных вычислений для каждого paintEvent QLabel, всякий раз, когда свойство scaledContents имеет значение True, масштабированное изображение кэшируется, и вся картина автоматически отбрасывается.

Чтобы избежать этого, следует создать Новый экземпляр QPixmap с использованием существующего, а затем снова установите новое нарисованное растровое изображение. Обратите внимание, что если изображение масштабируется, координаты виджета не будут отражать фактическую позицию на растровом изображении, поэтому вам нужно использовать преобразование, чтобы получить фактическую точку для рисования.

    def imgMousePress(self, e):
        pm = QPixmap(self.imglabel.pixmap())
        painter = QPainter(pm)
        pen = QPen()
        pen.setWidth(10)
        pen.setColor(QColor('red'))
        painter.setPen(pen)
        transform = QTransform().scale(
            pm.width() / self.imglabel.width(), 
            pm.height() / self.imglabel.height())
        painter.drawPoint(transform.map(e.pos()))
        painter.end()
        self.imglabel.setPixmap(pm)

Учтите, что все «точки» станут вытянутыми прямоугольниками, если отношение ширины к высоте не совпадает с исходным изображением, но это только проблема внешнего вида: если вы сохраните растровое изображение позже, они снова будут квадратными, поскольку сохранение основано на исходное растровое изображение.
Если вы хотите сохранить их квадратную форму при отображении, вам нужно отслеживать точки и перезаписывать paintEvent, чтобы рисовать их вручную на этикетке.

...