简体   繁体   English

使用PyQt5在QLabel中绘制图像

[英]Draw over image in a QLabel with PyQt5

I want to draw over image with my mouse. 我想用鼠标画出图像。 I simplified the problem by this code. 我通过这段代码简化了问题。 When i uncomment the line 31 the code doesn't work. 当我取消注释第31行时,代码不起作用。 My goal is to draw over the image i want to select from my PC and save the image after modify it. 我的目标是绘制我想从我的PC中选择的图像并在修改后保存图像。

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_())

Do not draw inside a widget outside of the paintEvent() . 不要小部件内绘制之外paintEvent() This is not supported by Qt. Qt不支持此功能。

You may draw on a QImage or QPixmap instead, and then in paintEvent() of your widget, draw that image. 您可以在QImageQPixmap上绘制,然后在窗口小部件的paintEvent()中绘制该图像。 Images can be initialized with all pixels transparent as well, if you like to composite several images (background+drawing) instead of drawing on the background directly. 如果您想要合成多个图像(背景+绘图)而不是直接在背景上绘图,则可以初始化所有像素的图像。

I think the way is best for you is using QLabel to view the image and OpenCV to draw over the image by those events. 我认为最好的方法是使用QLabel查看图像,使用OpenCV通过这些事件绘制图像。 The issue is you will need to refresh the image after each change. 问题是您需要在每次更改后刷新图像。 I did that in this project project , it is working, but it might be better to if you use QT library. 我在这个项目项目中做到了,它正在运行,但如果你使用QT库可能会更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM