【问题标题】:pyqt5 QLabel Image setScaledContents(True) don't allow Qpainter updatespyqt5 QLabel Image setScaledContents(True) 不允许 Qpainter 更新
【发布时间】:2020-03-11 17:54:59
【问题描述】:

我想在每次鼠标左键单击时显示一个图像并在当前鼠标位置放置一个标记。

下面的代码可以完成这项工作,但它只有在 ("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_())

【问题讨论】:

    标签: pyqt5 qlabel qimage qpixmap mousepress


    【解决方案1】:

    为避免对 QLabel 的每个paintEvent 进行不必要的计算,只要scaledContents 属性为 True,就会缓存缩放的图像,并自动丢弃所有绘画。

    为避免这种情况,您应该使用现有的 QPixmap 创建一个新实例,然后再次设置新绘制的 pixmap。请注意,如果图像被缩放,小部件坐标将不会反映像素图上的实际位置,因此您需要使用转换来获取要绘制的实际点。

        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 以在标签上手动绘制它们。

    【讨论】:

    • 谢谢,这行得通!我使用的图像分辨率非常高,在将它们缩放到一定程度后,所有imgMousePress 画家事件都非常慢。是否有任何解决方法可以使其快速响应?
    • @mvpavankumar 然后我建议对标签进行子类化,将点存储在列表中并仅在paintEvent中绘制它们,然后如果您需要保存生成的图像获取原始像素图,创建一个新的QPainter 就可以了,画点,end()painter 并保存 pixmap。
    猜你喜欢
    • 1970-01-01
    • 2019-04-23
    • 2019-10-20
    • 1970-01-01
    • 2017-03-07
    • 2021-05-25
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多