gpt4 book ai didi

python - PyQtGraph PlotWidget 在关闭窗口时使应用程序崩溃

转载 作者:行者123 更新时间:2023-11-28 18:02:52 26 4
gpt4 key购买 nike

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

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

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

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

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

  • App 类跟踪打开的窗口并存储图表数据。 (实际上,此类收集流数据并为相关打开的窗口调用更新例程。)
  • ButtonWindow 类可用于制作新的图表窗口。 (实际上,有很多按钮取决于用户希望绘制的图表。)
  • ChartWindow 类显示数据。

    import PyQt5.QtWidgets as qt
    import pyqtgraph as pg

    class App(qt.QApplication):
    def __init__(self,args):
    qt.QApplication.__init__(self,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(self)

    #enter event loop
    self.exec_()

    def new_window(cls):
    cls.windows[cls.last_idx] = ChartWindow(cls, cls.last_idx)
    cls.last_idx += 1

    def close_window(cls, window_id):
    cls.windows[window_id].destroy()
    del cls.windows[window_id]

    class ButtonWindow(qt.QWidget):
    def __init__(self, app):
    qt.QWidget.__init__(self)
    self.grid = qt.QGridLayout()
    self.app = app

    #add a button
    self.btn = qt.QPushButton('+1 Chart Window')
    self.btn.clicked.connect(self.app.new_window)
    self.grid.addWidget(self.btn,0,0)
    self.setLayout(self.grid)

    #show window
    self.show()

    class ChartWindow(qt.QWidget):
    def __init__(self, app, window_id):
    qt.QWidget.__init__(self)
    self.grid = qt.QGridLayout()
    self.app = app
    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)
    self.grid.addWidget(self.chart,0,0)
    self.setLayout(self.grid)

    #show window
    self.show()

    def closeEvent(cls,event):
    #cls.chart.close()
    cls.app.close_window(cls.window_id)

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

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

  1. > https://github.com/pyqtgraph/pyqtgraph/issues/55
  2. > parent for widgets - nescessary?

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

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

我也试过让所有小部件成为它们所在窗口的子窗口,但这没有效果。

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

最佳答案

不是从 closeEvent 调用一个消除自身的 close_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()

关于python - PyQtGraph PlotWidget 在关闭窗口时使应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55011097/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com