PyQtGraph PlotWidget 在关闭时使应用程序崩溃 window

PyQtGraph PlotWidget crashes application on closing window

我正在尝试构建一个桌面应用程序,它会在一些流数据到达时绘制图表。我希望能够打开多个 windows 来监控不同的流。

在我开始关闭图表之前,它工作得很好 windows。

我遇到的问题是,关闭我的一个图表 windows 经常会导致所有 windows 关闭并退出应用程序。终端中没有错误消息出现,所有 windows 都关闭并且程序终止。关闭图表 window 应该 只关闭图表 window.

我在 Windows 10 上使用 PyQt5、PyQtGraph 0.10.0 和 Python 3.6.1。

下面的代码显示了我的应用程序的结构。

仔细阅读后,我认为这是由于 Python 垃圾收集器与对底层 C++ 对象的幸存引用之间存在一些冲突。

  1. https://github.com/pyqtgraph/pyqtgraph/issues/55

这个问题肯定和PlotWidget有关。如果将绘图小部件换成按钮,则不会观察到崩溃。

我想在 1 的 closeEvent 覆盖中添加 'cls.chart.close()' 行。这有帮助。崩溃变得不那么频繁了,但是在 20 个左右的图表 window 关闭后,它仍然会发生。

我还尝试将所有小部件设为它们所在的 window 的子级,但这没有效果。

有什么想法吗?我无法相信像打开和关闭包含情节的 window 这样简单的事情足以炸毁 PyQt 所以我假设我在我的结构中做了一些愚蠢的事情。

而不是从 closeEvent 调用一个 close_window 来消除自身,换句话说,你试图在同一个 window 中消除 window 这就是 Qt 中的问题您必须使用信号来通知更改,在这种情况下,实现带有已关闭索引的关闭信号。

from PyQt5 import QtCore, QtWidgets
import pyqtgraph as pg

class App(QtWidgets.QApplication):
    def __init__(self, args):
        super(App, self).__init__(args)
        #window tracking
        self.last_idx = 0
        self.windows = {}

        #chart data
        self.x = [1,2,3,4,5]
        self.y = [1,2,3,4,5]

        #create button window
        self.button_window = ButtonWindow()

        #enter event loop
        self.exec_()

    @QtCore.pyqtSlot()
    def new_window(self):
        window = ChartWindow(self, self.last_idx)
        window.closed.connect(self.remove_window)
        self.windows[self.last_idx] = window
        self.last_idx += 1

    @QtCore.pyqtSlot(int)
    def remove_window(self, idx):
        w = self.windows[idx]
        w.deleteLater()
        del self.windows[idx]
        print(self.windows)

class ButtonWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ButtonWindow, self).__init__(parent)
        grid = QtWidgets.QGridLayout(self)
        self.btn = QtWidgets.QPushButton('+1 Chart Window')
        self.btn.clicked.connect(QtWidgets.QApplication.instance().new_window)
        grid.addWidget(self.btn, 0, 0)
        self.show()

class ChartWindow(QtWidgets.QWidget):
    closed = QtCore.pyqtSignal(int)

    def __init__(self, app, window_id):
        super(ChartWindow, self).__init__()
        grid = QtWidgets.QGridLayout(self)
        self.window_id = window_id
        self.setWindowTitle('Chart Window '+str(self.window_id))
        #add a chart
        self.chart = pg.PlotWidget()
        self.chart.plot(app.x,app.y)
        grid.addWidget(self.chart,0,0)
        #show window
        self.show()

    def closeEvent(self, event):
        self.closed.emit(self.window_id)
        super(ChartWindow, self).closeEvent(event)

def main():
    app = App([])
if __name__ == '__main__':
    main()