【问题标题】:Erasing pen on a canvas在画布上擦笔
【发布时间】:2019-04-30 02:46:52
【问题描述】:

我有一个功能正常的绘图应用程序,用于对图像进行一些分割。为此,我有两层,原始图像和我正在绘制的图像层。

我现在想实现一种擦除方法。我已经实现了撤消功能,但我还希望用户能够选择画笔“颜色”以便能够擦除特定部分,例如油漆中的橡皮擦。我认为这可以通过使用不透明的颜色进行绘制来实现,但这只会导致不绘制线条。

因此,我的目标是画一条线,去除图像层中的像素值,以便我可以看到底层图像

绘图MVP

from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QMenu, QAction
from PyQt5.QtGui import QIcon, QImage, QPainter, QPen
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtGui import QColor
import sys

class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        top = 400
        left = 400
        width = 800
        height = 600

        self.setWindowTitle("MyPainter")
        self.setGeometry(top, left, width, height)

        self.image = QImage(self.size(), QImage.Format_ARGB32)
        self.image.fill(Qt.white)
        self.imageDraw = QImage(self.size(), QImage.Format_ARGB32)
        self.imageDraw.fill(Qt.transparent)

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

        self.change = False
        mainMenu = self.menuBar()
        changeColour = mainMenu.addMenu("changeColour")
        changeColourAction = QAction("change",self)
        changeColour.addAction(changeColourAction)
        changeColourAction.triggered.connect(self.changeColour)

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

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

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

    def paintEvent(self, event):
        canvasPainter = QPainter(self)
        canvasPainter.drawImage(self.rect(), self.image, self.image.rect())
        canvasPainter.drawImage(self.rect(), self.imageDraw, self.imageDraw.rect())

    def changeColour(self):
        if not self.change:
            # erase
            self.brushColor = QColor(255,255,255,0)
        else:
            self.brushColor = Qt.black
        self.change = not self.change

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    app.exec()

如何擦除像素子集?

在这个例子中应该给self.brushColor 函数中的changeColour 赋予什么颜色?

信息

白色不是解决方案,因为实际上底部的图像是一个复杂的图像,因此我想在擦除时再次使顶层“透视”。

【问题讨论】:

  • 什么叫复杂图像?
  • @eyllanesc 只是许多不同的颜色,所以你不能假设任何关于底层图像的事情。这只是为了强调一点,变化应该只发生在顶层

标签: python pyqt pyqt5


【解决方案1】:

您必须将compositionMode 更改为QPainter::CompositionMode_Clear 并使用eraseRect() 擦除。

from PyQt5 import QtCore, QtGui, QtWidgets

class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        top, left, width, height = 400, 400, 800, 600
        self.setWindowTitle("MyPainter")
        self.setGeometry(top, left, width, height)

        self.image = QtGui.QImage(self.size(), QtGui.QImage.Format_ARGB32)
        self.image.fill(QtCore.Qt.white)
        self.imageDraw = QtGui.QImage(self.size(), QtGui.QImage.Format_ARGB32)
        self.imageDraw.fill(QtCore.Qt.transparent)

        self.drawing = False
        self.brushSize = 2
        self._clear_size = 20
        self.brushColor = QtGui.QColor(QtCore.Qt.black)
        self.lastPoint = QtCore.QPoint()

        self.change = False
        mainMenu = self.menuBar()
        changeColour = mainMenu.addMenu("changeColour")
        changeColourAction = QtWidgets.QAction("change", self)
        changeColour.addAction(changeColourAction)
        changeColourAction.triggered.connect(self.changeColour)

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

    def mouseMoveEvent(self, event):
        if event.buttons() and QtCore.Qt.LeftButton and self.drawing:
            painter = QtGui.QPainter(self.imageDraw)
            painter.setPen(QtGui.QPen(self.brushColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
            if self.change:
                r = QtCore.QRect(QtCore.QPoint(), self._clear_size*QtCore.QSize())
                r.moveCenter(event.pos())
                painter.save()
                painter.setCompositionMode(QtGui.QPainter.CompositionMode_Clear)
                painter.eraseRect(r)
                painter.restore()
            else:
                painter.drawLine(self.lastPoint, event.pos())
            painter.end()
            self.lastPoint = event.pos()
            self.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.image, self.image.rect())
        canvasPainter.drawImage(self.rect(), self.imageDraw, self.imageDraw.rect())

    def changeColour(self):
        self.change = not self.change
        if self.change:
            pixmap = QtGui.QPixmap(QtCore.QSize(1, 1)*self._clear_size)
            pixmap.fill(QtCore.Qt.transparent)
            painter = QtGui.QPainter(pixmap)
            painter.setPen(QtGui.QPen(QtCore.Qt.black, 2))
            painter.drawRect(pixmap.rect())
            painter.end()
            cursor = QtGui.QCursor(pixmap)
            QtWidgets.QApplication.setOverrideCursor(cursor)
        else:
            QtWidgets.QApplication.restoreOverrideCursor()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

【讨论】:

  • 一个问题,然后我会将其标记为已接受 :) 我可以轻松更改正方形的大小,但是尽管更改了 clear_size,但擦除区域仍然很小?
  • @JTIM 我觉得奇怪,矩形的面积等于擦除的面积。你可以指出你是如何实现它的,我认为你做错了,我没有你指出的问题
  • 啊忘了考虑我的缩放比例因子。谢谢;)
  • @JTIM 你看,没有minimal reproducible example 很难帮助:-)
  • 呵呵是的,但是整个项目太大了,而且很难进行缩放(至少对我来说;))。但是您的代码让我看到它应该可以工作,然后就很清楚了;)谢谢,祝您有美好的一天
猜你喜欢
  • 2020-10-22
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
  • 2019-01-30
  • 2011-04-16
相关资源
最近更新 更多