I'm writing Paint-like program on PyQt5. I encountered a problem during writing pen tool.
My idea: if currentMode == 1 (penMode key) and mouse pressed - then program creates circle with width value == self.width and color == self.color. But my program terminates with exit code -1073740791 (0xC0000409). I'm not native English and I can't find way to fix this problem.
My code (main part):
class TPaintWorker(QtWidgets.QMainWindow, TPaintGUI):
def __init__(self):
super().__init__()
self.setupUi(self)
self.currentMode = 0
self.width = 0
self.drawX = 0
self.drawY = 0
self.endX = 0
self.endY = 0
self.doPaint = False
self.color = QtGui.QColor(255, 255, 255)
self.penMode.clicked.connect(self.penDrawerActivate)
self.polygonMode.clicked.connect(self.polygonDrawerActivate)
self.circleMode.clicked.connect(self.circleDrawerActivate)
self.eraserMode.clicked.connect(self.eraserActivate)
self.saveImage.clicked.connect(self.saveProcess)
self.loadImage.clicked.connect(self.loadProcess)
def mousePressEvent(self, event):
if self.currentMode:
self.drawX = event.x
self.drawY = event.y
self.paintPrepare()
self.update()
def paintPrepare(self):
self.doPaint = True
self.repaint()
def paintEvent(self, event):
if self.doPaint:
qp = QtGui.QPainter()
qp.begin(self)
if self.currentMode == 1:
self.penDrawer(qp)
print("im out")
qp.end()
def penDrawerActivate(self):
self.currentMode = 1
self.width = QtWidgets.QInputDialog.getInt(self, "Input width value", "Width value:", 5, 1, 100, 1)
self.color = QtWidgets.QColorDialog.getColor(QtGui.QColor(255, 255, 255))
def penDrawer(self, qp):
print("im in")
self.pen = QtGui.QPen(self.color)
qp.setPen(self.pen)
qp.drawEllipse(self.drawX, self.drawY, self.width, self.width)
def polygonDrawerActivate(self):
self.currentMode = 2
self.dots = QtWidgets.QInputDialog.getInt(self, "Input number of dots", "Number of dots:", 4, 3, 25, 1)
self.width = QtWidgets.QInputDialog.getInt(self, "Input width value", "Width value:", 5, 1, 100, 1)
self.color = QtWidgets.QColorDialog.getColor(QtGui.QColor(255, 255, 255))
def circleDrawerActivate(self):
self.currentMode = 3
self.radius = QtWidgets.QInputDialog.getInt(self, "Input radius of circle", "Radius:", 50, 5, 200, 1)
self.width = QtWidgets.QInputDialog.getInt(self, "Input width value", "Width value:", 5, 1, 100, 1)
self.color = QtWidgets.QColorDialog.getColor(QtGui.QColor(255, 255, 255))
def eraserActivate(self):
self.currentMode = 4
self.width = QtWidgets.QInputDialog.getInt(self, "Input width of eraser", "Width value:", 50, 5, 200, 1)
def loadProcess(self):
loadPath, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Load image", "C:/", "PNG (*.png);;JPEG (*.jpg)")
if loadPath:
pixmap = QtGui.QPixmap(loadPath)
self.canvas.setPixmap(pixmap)
def saveProcess(self):
savePath, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save image", "C:/", "PNG (*.png);;JPEG (*.jpg)")
if savePath:
image = QtGui.QImage(self.canvas.pixmap())
image.save(savePath)
First of all, I suggest you to check the output of errors by running your program in a shell/prompt (note that IDEs sometimes are not completely able to show the full traceback): you'd have probably track your issues on your own.
The first problem is that you're not getting the coordinates in the mousePressEvent()
; in Qt, access to almost all properties is done through callables (except some very specific exceptions, like properties of QStyleOption subclasses).
The result is that drawX
and drawY
are not actually coordinates, but references to event.x
and event.y
functions respectively.
Then, all QInputDialog static methods return a tuple made of (value, accepted)
: the second value specifies if the dialog has been accepted or not (if the user pressed Cancel, Esc or closed the window).
Since you're setting all values to the full tuple, Qt will obviously crash whenever you're trying to use those values for drawing, as the related QPainter function will not accept those parameters; as a side note, consider that if the user doesn't accept the dialog (because maybe she/he clicked the wrong button), you should not set those values, nor go on asking other parameters.
Finally, two suggestions.
paintEvent
and add that widget to the main window.begin
and end
on the QPainter instance, as you can just create the instance with the paint device in the constructor (qp = QtGui.QPainter(self)
) and ignore the ending, since the painter will be automatically closed and correctly destroyed as soon as the paintEvent function returns.User contributions licensed under CC BY-SA 3.0