如何从MouseEvent在Qlabel中的图像顶部绘制多边形

问题描述 投票:0回答:1

使用Python,PYQT5,我想在Qlabel小部件中的图像上方绘制多边形。我使用了一个简单的Qmainwindow,它带有在QT设计器中生成的标签小部件(下面的代码)。

我知道在Qmainwindow中有一些关于abaut绘图的信息,如下所示:

让我知道,如果您有解决此问题的方法。

import sys
from PyQt5.QtCore import Qt
from PyQt5 import QtWidgets, uic, QtCore, QtGui
from PyQt5.QtGui import QPixmap, QPainter, QPolygon, QPen, QBrush
from PyQt5.QtCore import QPoint

from polygon_ui import Ui_MainWindow


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        pixmap = QPixmap("img.png")
        self.label.setPixmap(pixmap)

        self.label.mousePressEvent = self.getPixel
        self.pol = []

    def getPixel(self, event):
        x = event.pos().x()
        y = event.pos().y()

        self.pol.append(QPoint(int(x),int(y)))

        print(x,y, self.pol)

    def paintEvent(self, event):
        painter = QPainter(self)
        #painter.drawPixmap(self.rect(), self.image)

        painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
        painter.setBrush(QBrush(Qt.red, Qt.VerPattern))

        #points = QPolygon([ QPoint(10,10), QPoint(10,100),
        #     QPoint(100,10), QPoint(100,100)])

        points = QPolygon(self.pol)
        painter.drawPolygon(points)

    def mouseMoveEvent(self, event):
        pass

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

polygon_ui的代码在这里-只是由QT-Designer使用Mainwindow + Qlabel生成的:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(621, 641)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(10, 10, 600, 600))
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 621, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "TextLabel"))

python pyqt pyqt5 qlabel qpolygon
1个回答
0
投票

如果要在图像上添加诸如多边形,直线,圆形等元素,则不要使QLabel复杂化,因为例如,使用当前代码,您将在以下窗口中绘画QLabel,所以它不会被看到,与QLabel一起使用的可能解决方案是获取QPixmap并将其绘制在顶部。

[一个更好的选择是使用Qt Graphics Framework,其中将图像设置为QGraphicsPixmapItem,并将多边形设置为QGraphicsPixmapItem的子项,如下所示:

from PyQt5 import QtCore, QtGui, QtWidgets


class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)
        scene = QtWidgets.QGraphicsScene(self)
        self.setScene(scene)

        self._pixmap_item = QtWidgets.QGraphicsPixmapItem()
        scene.addItem(self.pixmap_item)

        self._polygon_item = QtWidgets.QGraphicsPolygonItem(self.pixmap_item)
        self.polygon_item.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
        self.polygon_item.setBrush(QtGui.QBrush(QtCore.Qt.red, QtCore.Qt.VerPattern))

    @property
    def pixmap_item(self):
        return self._pixmap_item

    @property
    def polygon_item(self):
        return self._polygon_item

    def setPixmap(self, pixmap):
        self.pixmap_item.setPixmap(pixmap)

    def resizeEvent(self, event):
        self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
        super().resizeEvent(event)

    def mousePressEvent(self, event):
        sp = self.mapToScene(event.pos())
        lp = self.pixmap_item.mapFromScene(sp)

        poly = self.polygon_item.polygon()
        poly.append(lp)
        self.polygon_item.setPolygon(poly)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        view = GraphicsView()
        self.setCentralWidget(view)

        view.setPixmap(QtGui.QPixmap("img.png"))

        self.resize(640, 480)


if __name__ == "__main__":

    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

更新:

如果要使用OP设计,则实现起来很简单:

  1. 创建一个名为graphicsview.py的文件,在其中实现GraphicsView逻辑:

    graphicsview.py

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class GraphicsView(QtWidgets.QGraphicsView):
        def __init__(self, parent=None):
            super().__init__(parent)
            scene = QtWidgets.QGraphicsScene(self)
            self.setScene(scene)
    
            self._pixmap_item = QtWidgets.QGraphicsPixmapItem()
            scene.addItem(self.pixmap_item)
    
            self._polygon_item = QtWidgets.QGraphicsPolygonItem(self.pixmap_item)
            self.polygon_item.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
            self.polygon_item.setBrush(QtGui.QBrush(QtCore.Qt.red, QtCore.Qt.VerPattern))
    
        @property
        def pixmap_item(self):
            return self._pixmap_item
    
        @property
        def polygon_item(self):
            return self._polygon_item
    
        def setPixmap(self, pixmap):
            self.pixmap_item.setPixmap(pixmap)
    
        def resizeEvent(self, event):
            self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
            super().resizeEvent(event)
    
        def mousePressEvent(self, event):
            sp = self.mapToScene(event.pos())
            lp = self.pixmap_item.mapFromScene(sp)
    
            poly = self.polygon_item.polygon()
            poly.append(lp)
            self.polygon_item.setPolygon(poly)
    
  2. 用QGraphicsView在Polygon_ui中替换QLabel:

    polygon_ui.py

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    from graphicsview import GraphicsView
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(621, 641)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.label = GraphicsView(self.centralwidget)
            self.label.setGeometry(QtCore.QRect(10, 10, 600, 600))
            self.label.setObjectName("label")
            # ...
  3. 还原main.py

    main.py

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    from polygon_ui import Ui_MainWindow
    
    
    class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, *args, obj=None, **kwargs):
            super(MainWindow, self).__init__(*args, **kwargs)
            self.setupUi(self)
    
            pixmap = QtGui.QPixmap("img.png")
            self.label.setPixmap(pixmap)
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec_())
    

另一种方法是升级窗口小部件,因此在这种类型中有很多示例,因此我省去了显示过程:

另一个更简单的选择是使用QLabel作为容器,并使用布局设置GraphicsView:

import sys

from PyQt5 import QtCore, QtGui, QtWidgets

from polygon_ui import Ui_MainWindow


class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)
        scene = QtWidgets.QGraphicsScene(self)
        self.setScene(scene)

        self._pixmap_item = QtWidgets.QGraphicsPixmapItem()
        scene.addItem(self.pixmap_item)

        self._polygon_item = QtWidgets.QGraphicsPolygonItem(self.pixmap_item)
        self.polygon_item.setPen(QtGui.QPen(QtCore.Qt.black, 5, QtCore.Qt.SolidLine))
        self.polygon_item.setBrush(QtGui.QBrush(QtCore.Qt.red, QtCore.Qt.VerPattern))

    @property
    def pixmap_item(self):
        return self._pixmap_item

    @property
    def polygon_item(self):
        return self._polygon_item

    def setPixmap(self, pixmap):
        self.pixmap_item.setPixmap(pixmap)

    def resizeEvent(self, event):
        self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
        super().resizeEvent(event)

    def mousePressEvent(self, event):
        sp = self.mapToScene(event.pos())
        lp = self.pixmap_item.mapFromScene(sp)

        poly = self.polygon_item.polygon()
        poly.append(lp)
        self.polygon_item.setPolygon(poly)


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        self.graphicsview = GraphicsView()
        lay = QtWidgets.QVBoxLayout(self.label)
        lay.addWiget(self.graphicsview)

        pixmap = QtGui.QPixmap("img.png")
        self.graphicsview.setPixmap(pixmap)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.