使用 PyQt5 在 QLabel 中绘制图像

Posted

技术标签:

【中文标题】使用 PyQt5 在 QLabel 中绘制图像【英文标题】:Draw over image in a QLabel with PyQt5 【发布时间】:2019-04-15 12:35:44 【问题描述】:

我想用鼠标在图像上绘制。 我通过这段代码简化了问题。 当我取消注释第 31 行时,代码不起作用。 我的目标是在我想​​从我的电脑中选择的图像上绘制并在修改后保存图像。

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(QtWidgets.QMainWindow):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(581, 463)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.selectImgeBtn = QtWidgets.QPushButton(self.centralwidget)
        self.selectImgeBtn.setGeometry(QtCore.QRect(50, 80, 121, 61))
        font = QtGui.QFont()
        font.setFamily("Roboto")
        font.setPointSize(11)
        self.selectImgeBtn.setFont(font)
        self.selectImgeBtn.setObjectName("selectImgeBtn")

        self.drawing = False
        self.brushSize = 2
        self.brushColor = QtCore.Qt.black
        self.lastPoint = QtCore.QPoint()

        self.imageLb = QtWidgets.QLabel(self.centralwidget)
        self.imageLb.setGeometry(QtCore.QRect(210, 10, 331, 201))
        self.imageLb.setFrameShape(QtWidgets.QFrame.Box)
        self.imageLb.setText("")
        self.imageLb.setObjectName("imageLb")
        self.imageLb.mousePressEvent = self.mousePressEvent
        self.imageLb.mouseMoveEvent = self.mouseMoveEvent
        self.imageLb.mouseReleaseEvent = self.mouseReleaseEvent
        # self.imageLb.paintEvent = self.paintEvent # When i uncomment this line the program is broken

        self.selectImgeBtn.clicked.connect(self.setImage)

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.selectImgeBtn.setText(_translate("MainWindow", "Select Image"))

    def setImage(self):
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png *.jpg *.jpeg *.bmp)")
        if fileName:
            pixmap = QtGui.QPixmap(fileName)
            pixmap = pixmap.scaled(self.imageLb.width(), self.imageLb.height(), QtCore.Qt.KeepAspectRatio)
            self.imageLb.setPixmap(pixmap)
            self.imageLb.setAlignment(QtCore.Qt.AlignCenter)

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.drawing = True
            self.lastPoint = event.pos()
            print(self.lastPoint)

    def mouseMoveEvent(self, event):
        if (event.buttons() == QtCore.Qt.LeftButton) and self.drawing:
            painter = QtGui.QPainter(self.imageLb)
            painter.setPen(QtGui.QPen(self.brushColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
            painter.drawLine(self.lastPoint, event.pos())
            self.lastPoint = event.pos()
            self.imageLb.update()

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.drawing = False

    def paintEvent(self, event):
        canvasPainter = QtGui.QPainter(self)
        canvasPainter.drawImage(self.rect(), self.imageLb, self.imageLb.rect())


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

【问题讨论】:

【参考方案1】:

不要paintEvent() 之外的小部件内绘制。 Qt 不支持此功能。

您可以改为在QImageQPixmap 上绘制,然后在小部件的paintEvent() 中绘制该图像。如果您想合成多张图像(背景+绘图)而不是直接在背景上绘图,也可以将图像初始化为所有像素透明。

【讨论】:

感谢您的回答,我是 PyQt5 的新手,这是我的第二天,所以我不明白该怎么做,但我会尝试。【参考方案2】:

我认为最适合您的方法是使用 QLabel 查看图像并使用 OpenCV 通过这些事件在图像上绘制。问题是您需要在每次更改后刷新图像。我在这个项目project 中做到了,它正在工作,但如果你使用 QT 库可能会更好。

【讨论】:

感谢您的回答,您的项目很棒。我将使用 OpenCV 完成一些任务,但现在我正在尝试使用 QT 库进行绘制。

以上是关于使用 PyQt5 在 QLabel 中绘制图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在每个 Qlabel PyQt5 中显示两个图像

如何在 PyQt5 中将字节数组图像添加到 QLabel

Pyqt5:使用Qlabel标签进行视频播放

如何使用 cv2.circle 在 Qlabel 内的图像上绘制一个圆圈

如何使用 pixmap 和 Qlabel 使图像可选择?

PyQt5 QLabel 错误