Как сделать окно для рисования мышью в 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"))
Есть ли какой-нибудь виджет, с помощью которого можно будет приближать и отдалять изображение?