Заполнение нарисованного пути с помощью QPainterPath в pyqt5

У меня есть QGraphicsView, в который загружено изображение. Затем я сделал так, чтобы вы могли рисовать по изображению своим указателем с помощью QPainterPath, а затем путь закрывался, соединяя начальную и конечную точки. Мне интересно, как заполнить эту область после отпускания мыши, а затем сделать этот объект выбираемым, но не перемещаемым.

Я попытался использовать QPaint и заполнить путь, как показано в функции addGraphicsItem.

class GraphicsView(QGraphicsView):
    def __init__(self, parent = None):
        super(GraphicsView, self).__init__(parent)
        self.setGeometry(300, 300, 250, 150)
        self.setScene(GraphicsScene(self))
        self.pixmapItem = QGraphicsPixmapItem() # check if everytime you open a new image the old image is still an item
        self.scene().addItem(self.pixmapItem)
        self.initial_path()

    def initial_path(self):
        self._path = QtGui.QPainterPath()
        pen = QtGui.QPen(QtGui.QColor("green"), 4, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap)
        self._path_item = self.scene().addPath(self._path, pen)

    @QtCore.pyqtSlot()
    def setImage(self):
        filename, _ = QFileDialog.getOpenFileName(None, "select Image", "", "Image Files (*.png *.jpg *jpg *.bmp)")
        if filename:
            self.image = QPixmap(filename)
            self.pixmapItem.setPixmap(QtGui.QPixmap(filename))

    def mousePressEvent(self, event):
        self.start = event.pos()
        if not self.pixmapItem.pixmap().isNull():
            self._path.moveTo(self.mapToScene(event.pos()))
            self._path_item.setPath(self._path)
        super(GraphicsView, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if not self.pixmapItem.pixmap().isNull():
            self._path.lineTo(self.mapToScene(event.pos()))
            self._path_item.setPath(self._path)
        super(GraphicsView, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        self.end = event.pos()
        if not self.pixmapItem.pixmap().isNull():
            self._path.lineTo(self.mapToScene(event.pos()))
            self._path.closeSubpath()
            self._path_item.setPath(self._path)
            self.addGraphicsItem()
            self.initial_path()
        super(GraphicsView, self).mouseReleaseEvent(event)

    def addGraphicsItem(self):
        pixmap = self.pixmapItem.pixmap()
        painter = QPainter(pixmap)
        painter.setRenderHint(QPainter.Antialiasing)
        pen = QPen(QtGui.QColor("green"), 4, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap)
        brush = QBrush(QColor('green'))
        painter.fillPath(self._path, brush)
        painter.end()

Я ожидал, что функция addGraphicsItem затем заполнит объект, но ничего не изменилось.


person Amanda.py    schedule 05.05.2019    source источник


Ответы (1)


Вместо использования QPainter вы можете продолжать использовать QGraphicsPainterPath, используя метод setBrush, вы можете установить цвет фона, а также вы можете установить флаг QGraphicsItem::ItemIsSelectable для выбора:

from PyQt5 import QtCore, QtGui, QtWidgets


class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super(GraphicsView, self).__init__(parent)
        self.setGeometry(300, 300, 250, 150)
        self.setScene(QtWidgets.QGraphicsScene(self))
        self.pixmapItem = (
            QtWidgets.QGraphicsPixmapItem()
        )  # check if everytime you open a new image the old image is still an item
        self.scene().addItem(self.pixmapItem)
        self._path_item = None

    def initial_path(self):
        self._path = QtGui.QPainterPath()
        pen = QtGui.QPen(
            QtGui.QColor("green"), 4, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap
        )
        self._path_item = self.scene().addPath(self._path, pen)

    @QtCore.pyqtSlot()
    def setImage(self):
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(
            None, "select Image", "", "Image Files (*.png *.jpg *jpg *.bmp)"
        )
        if filename:
            self.pixmapItem.setPixmap(QtGui.QPixmap(filename))

    def mousePressEvent(self, event):
        start = event.pos()
        if (
            not self.pixmapItem.pixmap().isNull()
            and event.buttons() & QtCore.Qt.LeftButton
        ):
            self.initial_path()
            self._path.moveTo(self.mapToScene(start))
            self._path_item.setPath(self._path)
        super(GraphicsView, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if (
            not self.pixmapItem.pixmap().isNull()
            and event.buttons() & QtCore.Qt.LeftButton
            and self._path_item is not None
        ):
            self._path.lineTo(self.mapToScene(event.pos()))
            self._path_item.setPath(self._path)
        super(GraphicsView, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        end = event.pos()
        if (
            not self.pixmapItem.pixmap().isNull()
            and self._path_item is not None
        ):
            self._path.lineTo(self.mapToScene(end))
            self._path.closeSubpath()
            self._path_item.setPath(self._path)
            self._path_item.setBrush(QtGui.QBrush(QtGui.QColor("red")))
            self._path_item.setFlag(
                QtWidgets.QGraphicsItem.ItemIsSelectable, True
            )
            self._path_item = None
        super(GraphicsView, self).mouseReleaseEvent(event)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = GraphicsView()
    w.setImage()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())
person eyllanesc    schedule 05.05.2019