Удаление нарисованных объектов PyQt
Код, который рисует примитивы на изображении.
Как теперь правильно написать удаление фигуры? Допустим, накидал прямоугольников и нужно удалить лишние. Мышкой выделяю нужный и удаляю. Как это правильно сделать?
import sys
from PyQt5 import QtCore, QtGui, QtWidgets # PyQt5
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.resize(600, 400)
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.pix = QtGui.QPixmap(600, 400)
self.pix.fill(QtCore.Qt.white)
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.drawPixmap(0, 0, self.pix)
br = QtGui.QBrush(QtGui.QColor("transparent"))
qp.setBrush(br)
if self.begin and self.end:
rect = QtCore.QRect(self.begin, self.end)
qp.drawRect(rect)
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.begin = event.pos()
self.end = self.begin
self.update()
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
self.end = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
painter = QtGui.QPainter(self.pix)
rect = QtCore.QRect(self.begin, self.end)
painter.drawRect(rect)
self.begin = self.end = QtCore.QPoint()
self.update()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWidget()
window.show()
sys.exit(app.exec_())
Ответы (1 шт):
Qt's Undo Framework - это реализация шаблона Command для реализации функций undo/redo в приложениях.
Шаблон Command основан на идее, что все редактирование в приложении выполняется путем создания экземпляров командных объектов.
Командные объекты применяют изменения к документу и сохраняются в стеке команд.
Более того, каждая команда знает, как отменить свои изменения, чтобы вернуть документ
в его предыдущее состояние.
Пока приложение использует только объекты команд для изменения состояния документа,
можно отменить последовательность команд, просматривая стек вниз и вызывая отмену для
каждой команды по очереди.
Также возможно повторить последовательность команд, просматривая стек вверх и вызывая повтор для каждой команды.
Больше https://doc.qt.io/qt-5/qundocommand.html#details
и
https://doc.qt.io/qt-5/qundostack.html#details
import sys
from PyQt5.QtWidgets import QMessageBox, QMainWindow, QApplication, \
QUndoCommand, QUndoStack
from PyQt5.QtGui import QPainter, QColor, QImage, QPen
from PyQt5.QtCore import Qt, QRectF, QRect
class UndoCommand(QUndoCommand):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.mPrevImage = parent.image.copy()
self.mCurrImage = parent.image.copy()
def undo(self):
self.mCurrImage = self.parent.image.copy()
self.parent.image = self.mPrevImage
self.parent.update()
def redo(self):
self.parent.image = self.mCurrImage
self.parent.update()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.mUndoStack = QUndoStack(self)
self.mUndoStack.setUndoLimit(20)
self.mUndoStack.canUndoChanged.connect(self.can_undo_changed)
self.mUndoStack.canRedoChanged.connect(self.can_redo_changed)
self.actionUndo = self.menuBar().addAction("Undo")
self.actionUndo.triggered.connect(self.mUndoStack.undo)
self.actionRedo = self.menuBar().addAction("Redo")
self.actionRedo.triggered.connect(self.mUndoStack.redo)
self.can_undo_changed(self.mUndoStack.canUndo())
self.can_redo_changed(self.mUndoStack.canRedo())
self.image = QImage(self.size(), QImage.Format_ARGB32)
self.image.fill(Qt.transparent)
self.start_pos = None
self.end_pos = None
self.is_pressed = False
def can_undo_changed(self, enabled):
self.actionUndo.setEnabled(enabled)
def can_redo_changed(self, enabled):
self.actionRedo.setEnabled(enabled)
def make_undo_command(self):
self.mUndoStack.push(UndoCommand(self))
def draw(self, parent):
painter = QPainter(parent)
painter.setRenderHint(QPainter.HighQualityAntialiasing)
painter.setPen(Qt.NoPen)
painter.setBrush(QColor('#9900917C'))
rect = QRect(self.start_pos, self.end_pos)
painter.drawEllipse(rect)
painter.setPen(QPen(Qt.red, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
painter.setBrush(QColor('#44fb743e'))
painter.drawRect(rect)
def paintEvent(self, event):
painter = QPainter(self)
painter.drawImage(self.image.rect(), self.image)
if self.is_pressed:
self.draw(self)
def mousePressEvent(self, event):
self.is_pressed = True
self.start_pos = event.pos()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
self.end_pos = event.pos()
self.update()
def mouseReleaseEvent(self, event):
self.is_pressed = False
self.end_pos = event.pos()
self.make_undo_command()
self.draw(self.image)
self.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.resize(600, 400)
w.show()
sys.exit(app.exec_())
