【问题标题】:The program terminates without warning [PyQt5]程序在没有警告的情况下终止 [PyQt5]
【发布时间】:2020-11-01 14:42:53
【问题描述】:

我正在 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)

【问题讨论】:

  • print("im in")print("im out)" - 我要调试和查找问题区域的东西

标签: python user-interface pyqt5


【解决方案1】:

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

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

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

最后,有两个建议。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    • 1970-01-01
    相关资源
    最近更新 更多