Сломанные фигуры - PullRequest
0 голосов
/ 23 сентября 2018

Пытаясь реализовать рисование, я решил начать с фигур Мой инициат:

 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 Прошу прощения за мой английский, если что-то не так с:

1 Ответ

0 голосов
/ 23 сентября 2018

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

Как вы заметили, вы должны сохранитьданные в изображении, если вы хотите, чтобы они остались, и временные данные, чтобы нарисовать их непосредственно в виджете.Логика моего решения заключается в том, что от mousePressEvent до момента, пока mouseReleaseEvent не будет нарисован непосредственно в виджете, а затем сохранен в изображении, для этого я создал класс с именем 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_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...