QSpacerItem 在实例化两次时使 pyQT 崩溃

Posted

技术标签:

【中文标题】QSpacerItem 在实例化两次时使 pyQT 崩溃【英文标题】:QSpacerItem crashes pyQT when instantiated twice 【发布时间】:2017-02-11 12:39:12 【问题描述】:

一年多来,我一直在我的 pyQt 应用程序https://github.com/chipmuenk/pyfda 中寻找一个令人讨厌的退出时崩溃错误,并且偶然发现了它:以下代码 sn-p

    self.cmbResponseType = QtGui.QComboBox(self)
    self.cmbFilterType = QtGui.QComboBox(self)
    self.cmbDesignMethod = QtGui.QComboBox(self)

    spacer = QtGui.QSpacerItem(1, 0, QtGui.QSizePolicy.Expanding,
                                     QtGui.QSizePolicy.Fixed)

    layHFilWdg = QtGui.QHBoxLayout() # container for filter subwidgets
    layHFilWdg.addWidget(self.cmbResponseType)
    layHFilWdg.addItem(spacer)
    layHFilWdg.addWidget(self.cmbFilterType)
    layHFilWdg.addItem(spacer)
    layHFilWdg.addWidget(self.cmbDesignMethod)

将三个组合框放置在水平布局框中,它们之间的间距可变。

当我注释掉两个layHFilWdg.addItem(spacer) 指令之一时,该错误消失了(退出时不再崩溃)。我正在使用 python 2.7 ... 3.5 和 pyQt 4.8。

我在应用程序中有很多选项卡式小部件(也有很多其他错误),并且在设计流程中以某种方式抑制错误太久,这就是我花了这么长时间的原因。只有当 matplotlib 画布在一个完全不相关的子小部件中实例化时才会发生崩溃,这只是另一个怪事,让我很长一段时间都在找错误的树......

有人知道上面代码的问题出在哪里吗?

【问题讨论】:

【参考方案1】:

这看起来像是 Python 垃圾收集器以 Qt 不期望的顺序删除对象的典型案例。向同一个布局多次添加间隔符可能会导致 Qt 尝试将其删除两次,或者在它不再存在时将其删除。显而易见的解决方案很简单:不要那样做。

所以要么每次创建一个新的垫片:

    def spacer():
        return QtGui.QSpacerItem(
            1, 0, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)

    ...

    layHFilWdg.addItem(spacer())

或者只使用布局的addStretch() 方法:

    layHFilWdg.addWidget(self.cmbResponseType)
    layHFilWdg.addStretch()

【讨论】:

有道理!其他小部件很难遇到类似的情况,您希望每个实例都有不同的行为,但是使用间隔... 至少对于 QT 4.8.7 来说,布局是双重删除分隔符......有时是一个难以捕捉的错误

以上是关于QSpacerItem 在实例化两次时使 pyQT 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Flask-Mail Mail()实例化两次

Django order_by将查询集随机化两次?

Pyqt:选择某些下拉值的值时使QLabel消失

UIView animationWithDuration 在调用两次时不起作用

recv 函数在使用两次时失败

使用torch.serialize两次时线程内存不足