Я пытаюсь создать настольное приложение, которое будет отображать некоторые потоковые данные по мере их поступления. Я хочу иметь возможность открывать несколько окон для мониторинга разных потоков.
Это работает довольно хорошо, пока я не начну закрывать окна графиков.
Проблема, с которой я столкнулся, заключается в том, что закрытие одного из окон моего графика часто приводит к закрытию всех окон и закрытию приложения. В терминале не появляются сообщения об ошибках, все окна просто закрываются и программа завершается. Закрытие окна графика должно закрывать только окно графика.
Я использую PyQt5, PyQtGraph 0.10.0 и Python 3.6.1 в Windows 10.
Приведенный ниже код показывает структуру моего приложения.
- Класс 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 ++.
- https://github.com/pyqtgraph/pyqtgraph/issues/55
- родитель для виджетов - необязательно?
Эта проблема определенно связана с PlotWidget. Сбоев не наблюдается, если виджет графика заменен на кнопку.
Мне пришла в голову идея добавить строку 'cls.chart.close ()' в переопределении closeEvent из 1 . Это помогает. Сбои становятся менее частыми, но через 20 или около того окно графика закрывается, но все равно происходит.
Я также пытался сделать все виджеты дочерними по отношению к окну, в котором они находятся, но это не имело никакого эффекта.
Есть идеи? Я не могу поверить, что что-то настолько простое, что открытия и закрытия окна, содержащего график, достаточно, чтобы взорвать PyQt, поэтому я предполагаю, что я делаю что-то глупое в своей структуре.