断铅笔

时间:2018-09-23 20:35:47

标签: 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()代替_begin.x(),需要使用event.x(),event.y()。

但这无法解决,因为在draw函数中,我无法将参数传递给“事件”。

当我尝试执行类似操作时,该函数使用=

请求事件
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()

1 个答案:

答案 0 :(得分:1)

似乎尚未理解形状绘制逻辑的解决方案,在拖动鼠标的形状中,必须擦除以前的形状,并且在释放鼠标时必须对其进行绘制在永久性存储器中,在这种情况下为QPixmap。但是对于铅笔,情况就不同了,因为在拖动时必须将其绘制在永久内存中,因此实现的类对此不起作用,因此我们必须在新类中实现它,记住在编程时要订购,每个班级必须有一个特定的任务。

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_())