MultiPlotWidget now uses scroll bar when plots do not fit in widget area.

This commit is contained in:
Luke Campagnola 2014-01-25 08:50:31 -05:00
parent d4364ea17a
commit 5a1a663a50
3 changed files with 47 additions and 24 deletions

View File

@ -22,7 +22,15 @@ pw = MultiPlotWidget()
mw.setCentralWidget(pw)
mw.show()
ma = MetaArray(random.random((3, 1000)), info=[{'name': 'Signal', 'cols': [{'name': 'Col1'}, {'name': 'Col2'}, {'name': 'Col3'}]}, {'name': 'Time', 'values': linspace(0., 1., 1000)}])
data = random.normal(size=(3, 1000)) * np.array([[0.1], [1e-5], [1]])
ma = MetaArray(data, info=[
{'name': 'Signal', 'cols': [
{'name': 'Col1', 'units': 'V'},
{'name': 'Col2', 'units': 'A'},
{'name': 'Col3'},
]},
{'name': 'Time', 'values': linspace(0., 1., 1000), 'units': 's'}
])
pw.plot(ma)
## Start Qt event loop unless running in interactive mode.

View File

@ -7,26 +7,23 @@ Distributed under MIT/X11 license. See license.txt for more infomation.
from numpy import ndarray
from . import GraphicsLayout
try:
from ..metaarray import *
HAVE_METAARRAY = True
except:
#raise
HAVE_METAARRAY = False
from ..metaarray import *
__all__ = ['MultiPlotItem']
class MultiPlotItem(GraphicsLayout.GraphicsLayout):
"""
Automaticaly generates a grid of plots from a multi-dimensional array
Automatically generates a grid of plots from a multi-dimensional array
"""
def __init__(self, *args, **kwds):
GraphicsLayout.GraphicsLayout.__init__(self, *args, **kwds)
self.plots = []
def plot(self, data):
#self.layout.clear()
self.plots = []
if HAVE_METAARRAY and (hasattr(data, 'implements') and data.implements('MetaArray')):
if hasattr(data, 'implements') and data.implements('MetaArray'):
if data.ndim != 2:
raise Exception("MultiPlot currently only accepts 2D MetaArray.")
ic = data.infoCopy()
@ -44,18 +41,14 @@ class MultiPlotItem(GraphicsLayout.GraphicsLayout):
pi.plot(data[tuple(sl)])
#self.layout.addItem(pi, i, 0)
self.plots.append((pi, i, 0))
title = None
units = None
info = ic[ax]['cols'][i]
if 'title' in info:
title = info['title']
elif 'name' in info:
title = info['name']
if 'units' in info:
units = info['units']
title = info.get('title', info.get('name', None))
units = info.get('units', None)
pi.setLabel('left', text=title, units=units)
info = ic[1-ax]
title = info.get('title', info.get('name', None))
units = info.get('units', None)
pi.setLabel('bottom', text=title, units=units)
else:
raise Exception("Data type %s not (yet?) supported for MultiPlot." % type(data))

View File

@ -4,21 +4,24 @@ MultiPlotWidget.py - Convenience class--GraphicsView widget displaying a MultiP
Copyright 2010 Luke Campagnola
Distributed under MIT/X11 license. See license.txt for more infomation.
"""
from ..Qt import QtCore
from .GraphicsView import GraphicsView
from ..graphicsItems import MultiPlotItem as MultiPlotItem
__all__ = ['MultiPlotWidget']
class MultiPlotWidget(GraphicsView):
"""Widget implementing a graphicsView with a single PlotItem inside."""
"""Widget implementing a graphicsView with a single MultiPlotItem inside."""
def __init__(self, parent=None):
self.minPlotHeight = 150
self.mPlotItem = MultiPlotItem.MultiPlotItem()
GraphicsView.__init__(self, parent)
self.enableMouse(False)
self.mPlotItem = MultiPlotItem.MultiPlotItem()
self.setCentralItem(self.mPlotItem)
## Explicitly wrap methods from mPlotItem
#for m in ['setData']:
#setattr(self, m, getattr(self.mPlotItem, m))
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
def __getattr__(self, attr): ## implicitly wrap methods from plotItem
if hasattr(self.mPlotItem, attr):
@ -27,6 +30,7 @@ class MultiPlotWidget(GraphicsView):
return m
raise AttributeError(attr)
def widgetGroupInterface(self):
return (None, MultiPlotWidget.saveState, MultiPlotWidget.restoreState)
@ -43,3 +47,21 @@ class MultiPlotWidget(GraphicsView):
self.mPlotItem = None
self.setParent(None)
GraphicsView.close(self)
def setRange(self, *args, **kwds):
GraphicsView.setRange(self, *args, **kwds)
if self.centralWidget is not None:
r = self.range
minHeight = len(self.mPlotItem.plots) * self.minPlotHeight
if r.height() < minHeight:
r.setHeight(minHeight)
r.setWidth(r.width() - 25)
self.centralWidget.setGeometry(r)
def resizeEvent(self, ev):
if self.closed:
return
if self.autoPixelRange:
self.range = QtCore.QRectF(0, 0, self.size().width(), self.size().height())
MultiPlotWidget.setRange(self, self.range, padding=0, disableAutoPixel=False) ## we do this because some subclasses like to redefine setRange in an incompatible way.
self.updateMatrix()