diff --git a/pyqtgraph/graphicsItems/HistogramLUTItem.py b/pyqtgraph/graphicsItems/HistogramLUTItem.py index 71577422..6a915902 100644 --- a/pyqtgraph/graphicsItems/HistogramLUTItem.py +++ b/pyqtgraph/graphicsItems/HistogramLUTItem.py @@ -17,6 +17,7 @@ from .. import functions as fn import numpy as np from .. import debug as debug +import weakref __all__ = ['HistogramLUTItem'] @@ -42,7 +43,7 @@ class HistogramLUTItem(GraphicsWidget): """ GraphicsWidget.__init__(self) self.lut = None - self.imageItem = None + self.imageItem = lambda: None # fake a dead weakref self.layout = QtGui.QGraphicsGridLayout() self.setLayout(self.layout) @@ -138,7 +139,7 @@ class HistogramLUTItem(GraphicsWidget): #self.region.setBounds([vr.top(), vr.bottom()]) def setImageItem(self, img): - self.imageItem = img + self.imageItem = weakref.ref(img) img.sigImageChanged.connect(self.imageChanged) img.setLookupTable(self.getLookupTable) ## send function pointer, not the result #self.gradientChanged() @@ -150,11 +151,11 @@ class HistogramLUTItem(GraphicsWidget): self.update() def gradientChanged(self): - if self.imageItem is not None: + if self.imageItem() is not None: if self.gradient.isLookupTrivial(): - self.imageItem.setLookupTable(None) #lambda x: x.astype(np.uint8)) + self.imageItem().setLookupTable(None) #lambda x: x.astype(np.uint8)) else: - self.imageItem.setLookupTable(self.getLookupTable) ## send function pointer, not the result + self.imageItem().setLookupTable(self.getLookupTable) ## send function pointer, not the result self.lut = None #if self.imageItem is not None: @@ -178,14 +179,14 @@ class HistogramLUTItem(GraphicsWidget): #self.update() def regionChanging(self): - if self.imageItem is not None: - self.imageItem.setLevels(self.region.getRegion()) + if self.imageItem() is not None: + self.imageItem().setLevels(self.region.getRegion()) self.sigLevelsChanged.emit(self) self.update() def imageChanged(self, autoLevel=False, autoRange=False): profiler = debug.Profiler() - h = self.imageItem.getHistogram() + h = self.imageItem().getHistogram() profiler('get histogram') if h[0] is None: return diff --git a/pyqtgraph/tests/test_ref_cycles.py b/pyqtgraph/tests/test_ref_cycles.py index 2154632e..3e78b382 100644 --- a/pyqtgraph/tests/test_ref_cycles.py +++ b/pyqtgraph/tests/test_ref_cycles.py @@ -7,54 +7,42 @@ import numpy as np import gc, weakref app = pg.mkQApp() -def processEvents(): - for i in range(3): - gc.collect() - app.processEvents() - # processEvents ignored DeferredDelete events; we must process these - # manually. - app.sendPostedEvents(None, pg.QtCore.QEvent.DeferredDelete) +def assert_alldead(refs): + for ref in refs: + assert ref() is None -#def test_PlotItem(): - #for i in range(10): - #plt = pg.PlotItem() - #plt.plot(np.random.normal(size=10000)) - #processEvents() - - #ot = pg.debug.ObjTracker() - - #plots = [] - #for i in range(10): - #plt = pg.PlotItem() - #plt.plot(np.random.normal(size=10000)) - #plots.append(plt) - #processEvents() - - #ot.diff() - - #del plots - #processEvents() - - #ot.diff() - - - #return ot +def mkrefs(*objs): + return map(weakref.ref, objs) def test_PlotWidget(): - def mkref(*args, **kwds): - iv = pg.PlotWidget(*args, **kwds) - return weakref.ref(iv) + def mkobjs(*args, **kwds): + w = pg.PlotWidget(*args, **kwds) + data = pg.np.array([1,5,2,4,3]) + c = w.plot(data, name='stuff') + w.addLegend() + + # test that connections do not keep objects alive + w.plotItem.vb.sigRangeChanged.connect(mkrefs) + app.focusChanged.connect(w.plotItem.vb.invertY) + + # return weakrefs to a bunch of objects that should die when the scope exits. + return mkrefs(w, c, data, w.plotItem, w.plotItem.vb, w.plotItem.getMenu(), w.plotItem.getAxis('left')) for i in range(5): - assert mkref()() is None + assert_alldead(mkobjs()) def test_ImageView(): - def mkref(*args, **kwds): - iv = pg.ImageView(*args, **kwds) - return weakref.ref(iv) + def mkobjs(): + iv = pg.ImageView() + data = np.zeros((10,10,5)) + iv.setImage(data) + + return mkrefs(iv, iv.imageItem, iv.view, iv.ui.histogram, data) for i in range(5): - assert mkref()() is None + assert_alldead(mkobjs()) + + if __name__ == '__main__': ot = test_PlotItem()