python - 绘图铅笔断了

标签 python python-3.x pyqt pyqt5

但在实现过程中,我遇到了一个不太清楚的事情。

工作铅笔实现代码:

import sys
from PyQt5.QtCore import QPoint, QRect, QSize, Qt
from PyQt5.QtGui import QPainter, QPen, QIcon, QPixmap, QColor
from PyQt5.QtWidgets import (QAction, QApplication, QMainWindow,QWidget)


class AbstractScribbleArea(QWidget):
    def __init__(self, parent=None):
        super(AbstractScribbleArea, self).__init__(parent)
        self.modified = False
        self._begin = QPoint()
        self._end = QPoint()
        self._lastPoint = QPoint()
        self._pixmap = QPixmap()
        self._shape = ""

        self.myPenWidth = 10
        self.myPenColor = QColor("black")

    def mousePressEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self._begin = event.pos()
            self._end = event.pos()
            self.update()
        super(AbstractScribbleArea, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self._end = event.pos()
            self.update()
        super(AbstractScribbleArea, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        # draw on image
        painter = QPainter(self._pixmap)
        if self._shape == 'pencil':
            painter.setPen(QPen(self.myPenColor, self.myPenWidth,
                                Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.draw(painter, self._begin, self._end, True)
        self._begin = QPoint()
        self._end = QPoint()
        self.update()
        super(AbstractScribbleArea, self).mouseReleaseEvent(event)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(self.rect(), self._pixmap, self.rect())
        if self._shape == 'pencil':
            painter.setPen(QPen(self.myPenColor, self.myPenWidth,
                                Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.draw(painter, self._begin, self._end, False)

    def resizeEvent(self, event):
        w = self.width() if self.width() > self._pixmap.width() else self._pixmap.width()
        h = self.height() if self.height() > self._pixmap.height() else self._pixmap.height()

        s = QSize(w, h)
        if s != self._pixmap.size():
            pixmap = QPixmap(self._pixmap)
            self._pixmap = QPixmap(s)
            painter = QPainter(self._pixmap)
            painter.fillRect(QRect(0, 0, w, h), Qt.white)
            painter.drawPixmap(pixmap.rect(), pixmap)
        super(AbstractScribbleArea, self).resizeEvent(event)

    def draw(self, painter, _begin, _end, is_released):
        raise NotImplementedError

    def sizeHint(self):
        return QSize(640, 480)

    def set_shape(self, shape):
        self._shape = shape

    def shape(self):
        return self._shape



class ScribbleArea(AbstractScribbleArea):
    def draw(self, painter, _begin, _end, is_released):
        if _begin.isNull() or _end.isNull():
            return
        elif self.shape() == "pencil":
            self.drawPencil(painter, _begin, _end)

    def drawPencil(self, painter, _begin, _end):
        self.modified = True
        painter.drawPoint(_begin.x(), _end.y())

    def pencilOn(self):
        self.set_shape("pencil")


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.scribbleArea = ScribbleArea()
        self.setCentralWidget(self.scribbleArea)

        self.pen = QAction(QIcon('Image/pen.png'), 'Карандаш', self)
        self.pen.triggered.connect(self.scribbleArea.pencilOn)
        toolbar = self.addToolBar('Инструменты')
        toolbar.addAction(self.pen)


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

问题是此时绘制的点可以沿轴移动。但这不是我等待的。我假设_end.y()需要使用event.x(),event.y()而不是_begin.x()。

但这不起作用,因为在绘图函数中我无法将参数传递给“事件”。

当我尝试执行类似操作时,该函数会使用 = 请求事件

def draw(self, painter, _begin, _end, is_released):
    if _begin.isNull() or _end.isNull():
        return
    elif self.shape() == "pencil":
        self.drawPencil(painter, event= #????)

def drawPencil(self, painter, _begin, _end):
    self.modified = True
    painter.drawPoint(event.x(), event.y())

我不太明白需要将什么传递给事件才能使函数正常工作。

铅笔功能还有一种实现:

def draw_pencil(self, event):
    painter.drawLine(self.lastPoint, event.pos())
    self.modified = True
    self._lastPoint = event.pos()
    self.update()

最佳答案

似乎还没有理解形状绘制逻辑的解决方案,在拖动鼠标时的形状的情况下,必须删除先前的形状,并且当释放鼠标时必须绘制它在永久内存中,在本例中为QPixmap。但对于铅笔来说,情况有所不同,因为在拖动时,它必须在永久内存中绘制,因此实现的类对其不起作用,因此我们必须在新类中实现它,请记住,在编程中,您有为了排序,每个类(class)必须有一个特定的任务。

from PyQt5 import QtCore, QtGui, QtWidgets


class AbstractShapeScribbleArea(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(AbstractShapeScribbleArea, self).__init__(parent)
        self._start = QtCore.QPoint()
        self._end = QtCore.QPoint()
        self._pixmap = QtGui.QPixmap() 
        self._shape = ""

        self._color = QtGui.QColor("black")
        self._pen_width = 1

        self._pen = QtGui.QPen(self._color, self._pen_width, 
            QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)

    def mousePressEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            self._start = event.pos()
            self._end = event.pos()
            self.update()
        super(AbstractShapeScribbleArea, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & QtCore.Qt.LeftButton:
            self._end = event.pos()
            self.update()
        super(AbstractShapeScribbleArea, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        painter = QtGui.QPainter(self._pixmap)
        painter.setPen(self._pen)
        self.draw_shape(painter, self._start, self._end, True)

        self._start = QtCore.QPoint()
        self._end = QtCore.QPoint()
        self.update()
        super(AbstractShapeScribbleArea, self).mouseReleaseEvent(event)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.drawPixmap(self.rect(), self._pixmap, self.rect())
        painter.setPen(self._pen)
        self.draw_shape(painter, self._start, self._end, False)

    def resizeEvent(self, event):
        w = self.width() if self.width() > self._pixmap.width() else self._pixmap.width()
        h = self.height() if self.height() > self._pixmap.height() else self._pixmap.height()

        s = QtCore.QSize(w, h)
        if s != self._pixmap.size():
            pixmap = QtGui.QPixmap(self._pixmap)
            self._pixmap = QtGui.QPixmap(s)
            painter = QtGui.QPainter(self._pixmap)
            painter.fillRect(QtCore.QRect(0, 0, w, h), QtCore.Qt.white)
            painter.drawPixmap(pixmap.rect(), pixmap)
        super(AbstractShapeScribbleArea, self).resizeEvent(event)

    def draw_shape(self, painter, start, end, is_released):
        raise NotImplementedError

    def sizeHint(self):
        return QtCore.QSize(640, 480)

    def set_pen_width(self, width):
        self._pen.setWidth(width)

    def set_pen_color(self, color):
        self._pen.setColor(QtGui.QColor(color))

    def set_shape(self, shape):
        self._shape =shape

    def shape(self):
        return self._shape


class ScribbleArea(AbstractShapeScribbleArea):
    def draw_shape(self, painter, start, end, is_released):
        if start.isNull() or end.isNull():
            return
        if self.shape() == "rectangle":
            self.draw_rectangle(painter, start, end)
        elif self.shape() == "ellipse":
            self.draw_ellipse(painter, start, end)

    def mousePressEvent(self, event):
        if self.shape() == "pencil" and event.buttons() & QtCore.Qt.LeftButton:
            setattr(self, "pencil_start", event.pos())
            self.draw_pencil(event.pos(), event.pos())
        else:
            super(ScribbleArea, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.shape() == "pencil" and event.buttons() & QtCore.Qt.LeftButton:
            pencil_start = getattr(self, "pencil_start")
            self.draw_pencil(pencil_start, event.pos())
            setattr(self, "pencil_start", event.pos())
        else:
            super(ScribbleArea, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.shape() == "pencil":
            delattr(self, "pencil_start")
        else:
            super(ScribbleArea, self).mouseReleaseEvent(event)

    def draw_rectangle(self, painter, start, end):
        rect = QtCore.QRect(start, end)
        painter.drawRect(rect)

    def draw_ellipse(self, painter, start, end):
        rect = QtCore.QRect(start, end)
        painter.drawEllipse(rect)

    def draw_pencil(self, start, end):
        painter = QtGui.QPainter(self._pixmap)
        painter.setPen(self._pen)
        painter.drawLine(start, end)
        self.update()

    @QtCore.pyqtSlot()
    def rectangleOn(self):
        self.set_shape("rectangle")

    @QtCore.pyqtSlot()
    def ellipseOn(self):
        self.set_shape("ellipse")

    @QtCore.pyqtSlot()
    def pencilOn(self):
        self.set_shape("pencil")


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

        rectangle = QtWidgets.QAction(QtGui.QIcon('Image/rectangle.png'), 'Rectangle', self)
        rectangle.triggered.connect(scribbleArea.rectangleOn)
        ellipse = QtWidgets.QAction(QtGui.QIcon('Image/Ellipse.png'), 'Ellipse', self)
        ellipse.triggered.connect(scribbleArea.ellipseOn)
        pen = QtWidgets.QAction(QtGui.QIcon('Image/pen.png'), 'Pencil', self)
        pen.triggered.connect(scribbleArea.pencilOn)
        toolbar = self.addToolBar('Tools')
        toolbar.addAction(rectangle)
        toolbar.addAction(ellipse)
        toolbar.addAction(pen)


if __name__ == '__main__':
    import sys

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

关于python - 绘图铅笔断了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52470040/

相关文章:

python - 线性拟合,包括 NumPy/SciPy 的所有错误

python - "_tkinter.TclError: image "pyimage4 "doesn' t 存在”

Python,请求,错误= http.client.BadStatusLine : <ServerStats>

python - QLineEdit 中的文本不显示

python - 使用 pyqt5 拖放(SIGNAL)

python - Pyomo: KeyError: "Index ' (0, 1, 1 )' is not valid for indexed component ' x_ijl'"

python - IntEnum 子类无法正确比较

python - 从 QValidator 获得视觉反馈

python - 使用 asyncio.Protocol 的客户端超时

python-3.x - 将 float 转换为具有数字和 nans 的列的整数