Qt5 строчит слоями — QPaintDevice: не удается уничтожить окрашиваемое устройство

#python #qt #pyqt5 #qgraphicsscene #qpainter

#python #qt #pyqt5 #qgraphicsscene #qpainter

Вопрос:

Я пытаюсь повторно реализовать демонстрационное приложение scribble для нескольких слоев изображений. Я изо всех сил пытаюсь нарисовать растровое изображение внутри сцены, поскольку художник жалуется, что оно уничтожается слишком рано.

QPaintDevice: не удается уничтожить окрашиваемое устройство

Не могли бы вы, пожалуйста, помочь мне исправить мой код таким образом, чтобы вы могли рисовать на растровом изображении roilayer красным пером и чтобы этот слой начинался прозрачным.

 #!/usr/bin/python3

import sys
import os
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap, QImage, QPainter, QPen
from PyQt5.QtCore import Qt, QRect


class Main(QGraphicsView):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Scribble with layers")
        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        self.image = QImage('sample/test.bmp')
        self.imlayer = QGraphicsPixmapItem(QPixmap.fromImage(self.image))
        self.roilayer = QGraphicsPixmapItem(QPixmap(self.image.size()))
        self.addlayer(self.imlayer)
        self.addlayer(self.roilayer)
        self.drawing = False
        self.lastPoint = None
        self.pencolour = Qt.red
        self.penwidth = 2
        self.show()

    def addlayer(self, layer):
        self.scene.addItem(layer)
        self.updateviewer()

    def updateviewer(self):
        self.fitInView(self.sceneRect(), Qt.KeepAspectRatio)

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

    def mouseMoveEvent(self, event):
        if (event.buttons() amp; Qt.LeftButton) and self.drawing:
            self.drawlineto(event.pos())

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

    def drawlineto(self, position):
        pixmap = self.roilayer.pixmap()
        painter = QPainter(pixmap)
        painter.setPen(QPen(self.pencolour, self.penwidth, Qt.SolidLine,
                Qt.RoundCap, Qt.RoundJoin))
        painter.drawLine(self.lastPoint, position)
        self.imlayer.setPixmap(pixmap)
        self.modified = True

        rad = self.penwidth / 2   2
        self.update(QRect(self.lastPoint, position).normalized().adjusted(-rad, -rad,  rad,  rad))
        self.lastPoint = position


if __name__ == '__main__':
    app = QApplication([])
    main = Main()
    sys.exit(app.exec_())
  

Комментарии:

1. Попробуйте добавить строку painter.end() непосредственно перед self.imlayer.setPixmap(pixmap) тем, как сообщить Qt, что вы закончили рисование.

2. Спасибо. Я не могу поверить, что это так просто, я нахожу документы для Painter запутанными.

3. привет, Jbbiomed. Можете ли вы дать мне несколько указаний, как заставить этот код работать? Я создаю простое приложение для рисования. Я попытался добавить painter.end(), как сказал @G.M. ранее, но у меня это не сработало.

Ответ №1:

У меня была та же проблема. Решение состоит в том, чтобы выполнить следующие действия в этой части вашего кода:

     def drawlineto(self, position):
        pixmap = self.roilayer.pixmap()
        painter = QPainter()
        painter.begin(pixmap)
        painter.setPen(QPen(self.pencolour, self.penwidth, Qt.SolidLine,
            Qt.RoundCap, Qt.RoundJoin))
        painter.drawLine(self.lastPoint, position)
        painter.end()
        self.imlayer.setPixmap(pixmap)
        self.modified = True