Как сделать окно для рисования мышью в PyQt5?

Я хотел сделать что-то по типу мини фотошопа на PyQt5. Я не знаю какой виджет использовать для окна рисования. Я пытался сделать его с помощью QGraphicsView, но он рисует объектами, а не пикселями, а если я буду рисовать с помощью QPainter, то не смогу нормально приближать изображение, как это происходит в QGraphicsView. Вот так у меня выглядит окно для рисования на QGraphicsView:

import sys
from PyQt5 import QtCore
from PyQt5 import QtGui, QtWidgets
from PyQt5 import uic
from main_window.py import Ui_MainWindow

from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog, QGraphicsView, QGraphicsScene, \
    QVBoxLayout

from PyQt5.QtWidgets import (QApplication, QLabel, QWidget)
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtGui import QPainter, QPainterPath, QPixmap
from PyQt5.QtCore import pyqtSignal, QObject, QPoint, QSize, QLineF, QRect
from PyQt5.QtWidgets import QMainWindow, QApplication


# Program

class GraphicsScene(QGraphicsScene):
    def __init__(self, parent=None):
        QGraphicsScene.__init__(self, parent)
        self.setSceneRect(0, 0, 100, 300)
        self.pen = QPen(Qt.black, 5)
        self.brush = QBrush(Qt.black, 5)
        self.lastScenePos = 0
        self.currentScenePos = 0
        self.pressed = False

    def mousePressEvent(self, event):
        self.pressed = True
        x = event.scenePos().x()
        y = event.scenePos().y()
        self.lastScenePos = (x, y)
        self.currentScenePos = (x, y)
        self.addRect(*self.lastScenePos, 1, 1, self.pen, self.brush)
        # self.addEllipse(*self.lastScenePos, 3, 3, self.pen, self.brush)
        print(x, y)

    def mouseReleaseEvent(self, event):
        self.pressed = False

    def mouseMoveEvent(self, event):
        if self.pressed:
            x = event.scenePos().x()
            y = event.scenePos().y()
            self.currentScenePos = (x, y)
            print(self.lastScenePos, 'last')
            print(self.currentScenePos, 'cur')
            print('---')
            self.addLine(QLineF(*self.lastScenePos, *self.currentScenePos), self.pen)
            # self.addEllipse(*self.currentScenePos, -3, -3, self.pen, self.brush)
            self.lastScenePos = (x, y)
            print(self.pressed)


class MyWidget(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.canvas.viewport().installEventFilter(self)
        self.init_UI()

    def init_UI(self):
        self.init_image()

        # активация функции сохранения
        self.actionSave.triggered.connect(self.save)

    def init_image(self):
        # Вставление изображение в поле редактирования
        # fname = QFileDialog.getOpenFileName(
        #     self, 'Выбрать картинку', '',
        #     'Картинка (*.jpg);;Все файлы (*)')[0]
        #
        # pixmap = QPixmap(fname)
        # self.canvas.setPixmap(pixmap)
        self.scene = GraphicsScene(self)
        self.canvas.setScene(self.scene)
        self.scene.installEventFilter(self)

    def save(self):
        # сохранение результата
        filePath, _ = QFileDialog.getSaveFileName(self, "Save Image", "",
                                                 "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")

        if filePath == "":
            return
        self.canvas.save(filePath)

    def eventFilter(self, source, event):
        if source == self.canvas.viewport() and event.type() == QEvent.Wheel:
            if event.angleDelta().y() > 0:
                scale = 1.25
            else:
                scale = .8
            self.canvas.scale(scale, scale)
            # do not propagate the event to the scroll area scrollbars
            return True
        elif event.type() == QEvent.GraphicsSceneMousePress:
            pass
        return super().eventFilter(source, event)


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

main_window:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1754, 1060)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setHorizontalSpacing(0)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_5.setObjectName("pushButton_5")
        self.horizontalLayout.addWidget(self.pushButton_5)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout.addWidget(self.pushButton_2)
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout.addWidget(self.pushButton_3)
        self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_4.setObjectName("pushButton_4")
        self.horizontalLayout.addWidget(self.pushButton_4)
        self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 1)
        self.gridLayout_3 = QtWidgets.QGridLayout()
        self.gridLayout_3.setContentsMargins(3, 3, 3, 3)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setContentsMargins(3, 3, 3, 3)
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.pushButton_9 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_9.setObjectName("pushButton_9")
        self.verticalLayout_5.addWidget(self.pushButton_9)
        self.gridLayout_3.addLayout(self.verticalLayout_5, 0, 2, 1, 1)
        self.verticalLayout_4 = QtWidgets.QVBoxLayout()
        self.verticalLayout_4.setContentsMargins(3, 3, 3, 3)
        self.verticalLayout_4.setSpacing(1)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.pushButton_8 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_8.setObjectName("pushButton_8")
        self.verticalLayout_4.addWidget(self.pushButton_8)
        self.pushButton_7 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_7.setObjectName("pushButton_7")
        self.verticalLayout_4.addWidget(self.pushButton_7)
        self.pushButton_6 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_6.setObjectName("pushButton_6")
        self.verticalLayout_4.addWidget(self.pushButton_6)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_4.addItem(spacerItem)
        self.gridLayout_3.addLayout(self.verticalLayout_4, 0, 0, 1, 1)
        self.gridLayout_4 = QtWidgets.QGridLayout()
        self.gridLayout_4.setContentsMargins(3, 3, 3, 3)
        self.gridLayout_4.setObjectName("gridLayout_4")
        spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        self.gridLayout_4.addItem(spacerItem1, 0, 1, 1, 1)
        self.canvas = QtWidgets.QGraphicsView(self.centralwidget)
        self.canvas.setObjectName("canvas")
        self.gridLayout_4.addWidget(self.canvas, 1, 1, 1, 1)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem2, 1, 0, 1, 1)
        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem3, 1, 2, 1, 1)
        spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        self.gridLayout_4.addItem(spacerItem4, 2, 1, 1, 1)
        self.gridLayout_3.addLayout(self.gridLayout_4, 0, 1, 1, 1)
        self.gridLayout_3.setColumnStretch(0, 1)
        self.gridLayout_3.setColumnStretch(1, 10)
        self.gridLayout_3.setColumnStretch(2, 3)
        self.gridLayout_2.addLayout(self.gridLayout_3, 1, 0, 1, 1)
        self.gridLayout_2.setRowStretch(0, 1)
        self.gridLayout_2.setRowStretch(1, 25)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1754, 21))
        self.menubar.setObjectName("menubar")
        self.menufile = QtWidgets.QMenu(self.menubar)
        self.menufile.setObjectName("menufile")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.actionOpen = QtWidgets.QAction(MainWindow)
        self.actionOpen.setObjectName("actionOpen")
        self.actionCreate = QtWidgets.QAction(MainWindow)
        self.actionCreate.setObjectName("actionCreate")
        self.actionSave = QtWidgets.QAction(MainWindow)
        self.actionSave.setObjectName("actionSave")
        self.menufile.addSeparator()
        self.menufile.addAction(self.actionOpen)
        self.menufile.addAction(self.actionCreate)
        self.menufile.addAction(self.actionSave)
        self.menubar.addAction(self.menufile.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton_5.setText(_translate("MainWindow", "PushButton"))
        self.pushButton.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_2.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_3.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_4.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_9.setText(_translate("MainWindow", "PushButton"))
        self.pushButton_8.setText(_translate("MainWindow", "1"))
        self.pushButton_7.setText(_translate("MainWindow", "1"))
        self.pushButton_6.setText(_translate("MainWindow", "1"))
        self.menufile.setTitle(_translate("MainWindow", "File"))
        self.actionOpen.setText(_translate("MainWindow", "Create new"))
        self.actionCreate.setText(_translate("MainWindow", "Open"))
        self.actionSave.setText(_translate("MainWindow", "Save"))

Есть ли какой-нибудь виджет, с помощью которого можно будет приближать и отдалять изображение?


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