首页 > 解决方案 > 程序在没有警告的情况下终止 [PyQt5]

问题描述

我正在 PyQt5 上编写类似 Paint 的程序。我在编写钢笔工具时遇到了问题。

我的想法:如果 currentMode == 1(penMode 键)并按下鼠标 - 然后程序创建宽度值 == self.width 和颜色 == self.color 的圆圈。但是我的程序以退出代码 -1073740791 (0xC0000409) 终止。我不是英语母语,我找不到解决这个问题的方法。

我的代码(主要部分)

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)

标签: pythonuser-interfacepyqt5

解决方案


首先,我建议您通过在 shell/prompt 中运行程序来检查错误输出(请注意,IDE 有时不能完全显示完整的回溯):您可能会自己跟踪问题。

第一个问题是您没有获得 ; 中的坐标mousePressEvent()。在 Qt 中,对几乎所有属性的访问都是通过可调用对象完成的(除了一些非常特殊的例外,例如 QStyleOption 子类的属性)。
结果是drawXanddrawY实际上不是坐标,而是分别引用和函数。event.xevent.y

然后,所有 QInputDialog 静态方法返回一个由 组成的元组(value, accepted):第二个值指定对话框是否已被接受(如果用户按下取消,Esc或关闭窗口)。
由于您将所有值设置为完整元组,因此当您尝试使用这些值进行绘图时,Qt 显然会崩溃,因为相关的 QPainter 函数将不接受这些参数;作为旁注,请考虑如果用户不接受对话框(因为也许她/他单击了错误的按钮),您不应该设置这些值,也不应该继续询问其他参数。

最后,提出两个建议。

  1. 除非确实需要,否则不应在主窗口上绘画;这是因为 QMainWindow 是一种非常特殊的 QWidget,并且具有一组特定的功能,这些功能可能会导致自定义绘制问题;应该首选在专用的 QWidget上绘图。这可以通过在该小部件(可能是中央小部件)上安装事件过滤器并在检测到绘制事件时绘制来完成,或者通过子类化 QWidget,实现它自己的paintEvent并将小部件添加到主窗口。
  2. (这很简单,但它可以稍微简化您的代码)您不需要手动调用QPainter 实例beginend因为您可以在构造函数 ( qp = QtGui.QPainter(self)) 中使用绘图设备创建实例并忽略结尾,因为一旦 paintEvent 函数返回,painter 将自动关闭并正确销毁。

推荐阅读