繁体   English   中英

破碎的绘图形状

[英]Broken drawing shapes

在尝试实现绘画时,我决定从形状开始我的初始化:

 def __init__(self, parent=None): 
    self.modified = False
    self.rectangle = False
    self.ellipse = False
    self.begin = QPoint()
    self.end = QPoint()
    self.myPenWidth = 1
    self.myFigureColor = Qt.black
    self.image = QImage()

我有一个事件,其中有绘制形状的函数

def mousePressEvent(self, event):
    if (event.button() == Qt.LeftButton) and self.rectangle:
        self.draw_rectandle(event)
    if (event.button() == Qt.LeftButton) and self.ellipse:
        self.draw_ellipse(event)

这里我们使用位于绘图图形中的函数:我将在下面发布它们

def mouseMoveEvent(self, event):
    if (event.buttons() & Qt.LeftButton) and self.rectangle:
        self.end = event.pos()
        self.update()
    if (event.buttons() & Qt.LeftButton) and self.ellipse:
        self.end = event.pos()
        self.update()

def mouseReleaseEvent(self, event):
    if (event.buttons() & Qt.LeftButton) and self.rectangle:
        self.begin = event.pos()
        self.end = event.pos()
    if (event.buttons() & Qt.LeftButton) and self.ellipse:
        self.begin = event.pos()
        self.end = event.pos()

另一个函数paintEvent:

def paintEvent(self, event):
    painter = QPainter(self)
    dirtyRect = event.rect()
    painter.drawImage(dirtyRect, self.image, dirtyRect)
    if self.rectangle == True:
        painter.setPen(QPen(self.myFigureColor, self.myPenWidth,
                            Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawRect(QRect(self.begin, self.end))
    if self.ellipse == True:
        painter.setPen(QPen(self.myFigureColor, self.myPenWidth,
                            Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawEllipse(QRect(self.begin, self.end))

数字本身的功能:

def draw_rectandle(self, event):
    painter = QPainter(self.image)
    painter.setPen(QPen(self.myFigureColor, self.myPenWidth,
                        Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
    painter.drawRect(QRect(self.begin, self.end))
    self.begin = event.pos()
    self.end = event.pos()
    self.modified = True
    self.update()

def draw_ellipse(self, event):
    painter = QPainter(self.image)
    painter.setPen(QPen(self.myFigureColor, self.myPenWidth,
                        Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
    painter.drawEllipse(QRect(self.begin, self.end))
    self.begin = event.pos()
    self.end = event.pos()
    self.modified = True
    self.update()

还有“伪绑定”

def rectangleOn(self):
    self.ellipse = False
    self.rectangle = True

def ellipseOn(self):
    self.rectangle = False
    self.ellipse = True

它们用于在按下形状按钮时更改功能标志。 如果您需要,按钮本身看起来像:

行动:

    self.rectangle = QAction(QIcon('Image/rectangle.png'), 'Rectangle', self)
    self.rectangle.triggered.connect(self.scribbleArea.rectangleOn)

    self.ellipse = QAction(QIcon('Image/Ellipse.png'), 'Ellipse', self)
    self.ellipse.triggered.connect(self.scribbleArea.ellipseOn)

带按钮的工具栏:

    toolbar = self.addToolBar('Tools')
    toolbar.addAction(self.rectangle)
    toolbar.addAction(self.ellipse)

我认为不需要一个函数来改变颜色和大小。 因此,虽然我不会发布。

现在我来告诉你问题是什么。

在paintEvent中,我有一张显示形状的图。 也就是说,我们拉动边缘,看看形状如何变化。 但是从那里它不会保存在任何地方。

并且在 mousePressEvent 中已经绘制了没有这个拖动动画的矩形本身

似乎一切都很好,但这里有一个错误

如您所见,矩形的绘制进入 mousePressEvent。 这意味着矩形仅在我开始绘制下一个时才会出现。 这已经是一个错误。 但! 如果我画几个矩形并开始画一个椭圆,最后一个矩形就会变成一个椭圆。

还有我的其他形状。

如果我开始画一条线,然后切换到一个椭圆,在另一个地方开始画椭圆,我画的线会立刻变成一个很窄的椭圆。

因此,我需要以某种方式从 mousePressEvent 中提取此函数,以便通过工具之间的这种切换来绘制所需的形状。

如果您需要更多详细信息,请写下 с:

PS,如果有什么问题,我为我的英语道歉с:

我无法重现,因为您将代码显示为碎片,我建议您始终显示统一的代码,以便我们可以轻松执行我们想要帮助的代码。

正如您所注意到的,如果您希望保留图像中的数据以及直接在小部件中绘制它们的临时数据,则必须保存图像中的数据。 我的解决方案的逻辑是从mousePressEventmouseReleaseEvent直接在小部件中绘制之前的瞬间,然后保存在图像中,为此我创建了一个名为AbstractScribbleArea的类来实现该一般逻辑,如果您想实现该逻辑对于其他形状,您应该只覆盖draw()方法。

from PyQt5 import QtCore, QtGui, QtWidgets


class AbstractScribbleArea(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(AbstractScribbleArea, 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(AbstractScribbleArea, self).mousePressEvent(event)

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

    def mouseReleaseEvent(self, event):
        # draw on image
        painter = QtGui.QPainter(self._pixmap)
        painter.setPen(self._pen)
        self.draw(painter, self._start, self._end, True)

        self._start = QtCore.QPoint()
        self._end = QtCore.QPoint()
        self.update()
        super(AbstractScribbleArea, 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(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(AbstractScribbleArea, self).resizeEvent(event)

    def draw(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(AbstractScribbleArea):
    def draw(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 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)

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

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


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.scribbleArea = ScribbleArea()
        self.scribbleArea.set_pen_width(10)
        self.scribbleArea.set_pen_color("red")
        self.setCentralWidget(self.scribbleArea)
        self.rectangle = QtWidgets.QAction(QtGui.QIcon('Image/rectangle.png'), 'Rectangle', self)
        self.rectangle.triggered.connect(self.scribbleArea.rectangleOn)
        self.ellipse = QtWidgets.QAction(QtGui.QIcon('Image/Ellipse.png'), 'Ellipse', self)
        self.ellipse.triggered.connect(self.scribbleArea.ellipseOn)
        toolbar = self.addToolBar('Tools')
        toolbar.addAction(self.rectangle)
        toolbar.addAction(self.ellipse)


if __name__ == '__main__':
    import sys

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM