Выделение и копирование определенной области

В инструментах есть выделение прямоугольной области. Оно должно копировать и вствалять выделенную область.

Также у меня не растягивается вставленное фото на полной экран. Помогите пожалуйста

import sys

from PyQt5.QtGui import QPainter, QPen, QImage
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog, QAction
from PyQt5.QtCore import Qt, QRectF, QPointF


class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setGeometry(300, 300, 600, 600)

        mainMenu = self.menuBar()
        instmenu = mainMenu.addMenu("Инстументы")
        file = mainMenu.addMenu("Файл")

        brush = QAction("Кисть", self)
        instmenu.addAction(brush)
        brush.triggered.connect(self.setBrush)

        rect = QAction("Прямоугольник", self)
        instmenu.addAction(rect)
        rect.triggered.connect(self.setRectangle)

        photo = QAction("Вставить фото", self)
        file.addAction(photo)
        photo.triggered.connect(self.getImage)

        self.image = QImage(self.size(), QImage.Format_ARGB32)
        self.image.fill(Qt.transparent)

        self.instrument = 'brush'

        self.brushColor = Qt.black
        self.brushSize = 8

        self.start_pos = QPointF()
        self.end_pos = QPointF()

        self.brush_points = []

        self.image = QImage(self.size(), QImage.Format_ARGB32)
        self.image.fill(Qt.transparent)

    def getImage(self):
        filename = QFileDialog.getOpenFileName(
            self, "", "",
            "Images(*.png *.jpg *.jpeg);;PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*)"
        )[0]
        if not filename:
            return
        self.image.load(filename)

    def draw(self, canvas):
        painter = QPainter(canvas)
        painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine))

        if self.instrument == 'brush':
            for i in self.brush_points:
                painter.drawPoint(i)

        elif self.instrument == 'rectangle':
            painter.setPen(QPen(Qt.red, self.brushSize, Qt.DashLine))
            painter.drawRect(QRectF(self.start_pos, self.end_pos))

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawImage(self.image.rect(), self.image)

        self.draw(self)

    def mousePressEvent(self, event):
        self.start_pos = event.pos()
        self.brush_points.clear()

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.end_pos = event.pos()
            self.brush_points.append(self.end_pos)

            self.update()

    def mouseReleaseEvent(self, event):
        self.end_pos = event.pos()
        self.brush_points.append(self.end_pos)

        self.draw(self.image)
        self.update()

    def setBrush(self):
        self.instrument = 'brush'

    def setRectangle(self):
        self.instrument = 'rectangle'


if __name__ == '__main__':
    app = QApplication(sys.argv)
    wnd = Window()
    wnd.show()
    sys.exit(app.exec())

Ответы (1 шт):

Автор решения: S. Nick

я добавил в меню опцию Выделить для копирования и отметил по тексту изменения, которые внес.

Свое делаете как и делали, я ничего не трогал.

Когда надо вырезать что-нибудь - сделайте клик по меню, зажав ЛКМ выделяете участок, отпускаете ЛКМ и все. Появившееся новое изображение можете перетаскивать как обычное окно.

import sys

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *

from PyQt5.QtGui import QPainter, QPen, QImage
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QFileDialog
from PyQt5.QtCore import Qt, QRectF, QPointF

from PIL import ImageGrab                                                  # +++
import numpy as np                                                         # +++
import cv2                                                                 # +++


class Label(QLabel):
    def __init__(self, img, parent=None):
        super(Label, self).__init__(parent)
        self.setCursor(Qt.PointingHandCursor)
        self.pixmapImagen = QPixmap(img) 
        self.setPixmap(self.pixmapImagen)
        self.setAlignment(Qt.AlignCenter)
        
    def mousePressEvent(self, event):
        self.origin = event.pos()
        super().mousePressEvent(event)
        
    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.move(event.windowPos().toPoint() - self.origin)
        super().mouseMoveEvent(event)


class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        mainMenu = self.menuBar()
        instmenu = mainMenu.addMenu("Инстументы")
        file = mainMenu.addMenu("Файл")
        brush = QAction("Кисть", self)
        instmenu.addAction(brush)
        brush.triggered.connect(self.setBrush)
        videlenie = QAction("Прямоугольное выделение", self)
        instmenu.addAction(videlenie)
        videlenie.triggered.connect(self.setVid)
        videlenie = QAction("Выделить для копирования", self)        # +++
        instmenu.addAction(videlenie)                                # +++
        videlenie.triggered.connect(self.screenshot)                 # +++
        photo = QAction("Вставить фото", self)
        file.addAction(photo)
        photo.triggered.connect(self.getImage)

        self.image_foreground = QImage(self.size(), QImage.Format_ARGB32_Premultiplied)
        self.image_foreground.fill(Qt.transparent)
        self.image_background = QImage(self.size(), QImage.Format_ARGB32_Premultiplied)
        self.image_background.fill(Qt.white)

        self.brushColor = Qt.blue         # black
        self.brushSize = 8
        self.instrument = 'brush'
        self.coords = QPointF()

        self.selection = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self) # +++
        self.start = QPointF() 
        self.end = QPointF()        

    def getImage(self):
        filename, _ = QFileDialog.getOpenFileName(
            self, 
            "Выберите изображение", 
            "",
            "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*)"
        )
        if not filename:
            return
        self.image_background.load(filename)
        self.selection.hide()                                # +++

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawImage(self.rect(), self.image_background, self.image_background.rect())
        painter.drawImage(self.image_foreground.rect(), self.image_foreground)

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton and self.instrument == 'brush':
            self.coords = event.pos()
        elif event.buttons() == Qt.LeftButton and self.instrument == 'rectangle':
            self.coords = event.pos()
        elif event.buttons() == Qt.LeftButton and self.instrument == 'screenshot':     # +++
            self.start = event.pos() 
            self._start = event.globalPos()

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton and self.instrument == 'brush':
            painter = QPainter(self.image_foreground)
            painter.setPen(QPen(self.brushColor, self.brushSize, Qt.SolidLine))
            painter.drawLine(self.coords, event.pos())
            self.coords = event.pos()
            self.update()
        elif event.buttons() == Qt.LeftButton and self.instrument == 'rectangle':
            self.update()
        elif event.buttons() == Qt.LeftButton and self.instrument == 'screenshot':      # +++
            self.end = event.pos()
            self.selection.setGeometry(QtCore.QRect(self.start, self.end).normalized())
            self.selection.show()

    def mouseReleaseEvent(self, event):
        if self.instrument == 'rectangle':
            painter = QPainter(self.image_foreground)
            painter.setPen(QPen(Qt.red, self.brushSize, Qt.DashLine))
            painter.drawRect(QRectF(self.coords, event.pos()))
            self.update()
        elif self.instrument == 'screenshot':                                            # +++
            self._end = event.globalPos()
            self.selection.hide()
            QtCore.QTimer.singleShot(20, self.newLabel)

    def newLabel(self):
        self.selection.hide()
        self.instrument = 'None'
        img = ImageGrab.grab(bbox=(
            self._start.x(), 
            self._start.y(), 
            self._end.x(), 
            self._end.y()
        ))
        
        pathImage = 'new_image.png'      # тут будет обрезанное изображение
        img.save(pathImage)
        img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
        cv2.waitKey(0)
        cv2.destroyAllWindows()        

        self.labelImagen = Label(pathImage, self)
        self.labelImagen.resize(self.selection.size())                          
        self.labelImagen.show()

    def setBrush(self):
        self.instrument = 'brush'
        self.selection.hide()

    def setVid(self):
        self.instrument = 'rectangle'
        self.selection.hide()
        
    def screenshot(self):                                                           # +++
        self.instrument = 'screenshot'
        
    def sizeHint(self):                                                             # +++
        return QtCore.QSize(500, 500)    
        
    def resizeEvent(self, event):                                                   # +++
        self.image_foreground = QImage(self.size(), QImage.Format_ARGB32_Premultiplied)
        self.image_foreground.fill(Qt.transparent)
        self.update()
        super().resizeEvent(event)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    wnd = Window()
    wnd.show()
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка