minor bugfixes / features:

- optional context menu for ImageItem
 - inverted y-axis in Canvas (+y now points upward)
 - extra __init__ arguments for Dock
 - Transform can be constructed from Matrix4x4
 - many others
This commit is contained in:
Luke Campagnola 2012-05-29 23:18:34 -04:00
parent 2c80098cf6
commit f258c3d87c
14 changed files with 144 additions and 245 deletions

View File

@ -32,6 +32,7 @@ class MouseDragEvent:
self._buttons = moveEvent.buttons() self._buttons = moveEvent.buttons()
self._button = pressEvent.button() self._button = pressEvent.button()
self._modifiers = moveEvent.modifiers() self._modifiers = moveEvent.modifiers()
self.acceptedItem = None
def accept(self): def accept(self):
"""An item should call this method if it can handle the event. This will prevent the event being delivered to any other items.""" """An item should call this method if it can handle the event. This will prevent the event being delivered to any other items."""
@ -160,7 +161,7 @@ class MouseClickEvent:
self._buttons = pressEvent.buttons() self._buttons = pressEvent.buttons()
self._modifiers = pressEvent.modifiers() self._modifiers = pressEvent.modifiers()
self._time = ptime.time() self._time = ptime.time()
self.acceptedItem = None
def accept(self): def accept(self):
"""An item should call this method if it can handle the event. This will prevent the event being delivered to any other items.""" """An item should call this method if it can handle the event. This will prevent the event being delivered to any other items."""

View File

@ -2,6 +2,7 @@
from .Qt import QtCore, QtGui from .Qt import QtCore, QtGui
from .Point import Point from .Point import Point
import numpy as np import numpy as np
import pyqtgraph as pg
class Transform(QtGui.QTransform): class Transform(QtGui.QTransform):
"""Transform that can always be represented as a combination of 3 matrices: scale * rotate * translate """Transform that can always be represented as a combination of 3 matrices: scale * rotate * translate
@ -11,7 +12,9 @@ class Transform(QtGui.QTransform):
QtGui.QTransform.__init__(self) QtGui.QTransform.__init__(self)
self.reset() self.reset()
if isinstance(init, dict): if init is None:
return
elif isinstance(init, dict):
self.restoreState(init) self.restoreState(init)
elif isinstance(init, Transform): elif isinstance(init, Transform):
self._state = { self._state = {
@ -22,6 +25,10 @@ class Transform(QtGui.QTransform):
self.update() self.update()
elif isinstance(init, QtGui.QTransform): elif isinstance(init, QtGui.QTransform):
self.setFromQTransform(init) self.setFromQTransform(init)
elif isinstance(init, QtGui.QMatrix4x4):
self.setFromMatrix4x4(init)
else:
raise Exception("Cannot create Transform from input type: %s" % str(type(init)))
def getScale(self): def getScale(self):
@ -65,6 +72,18 @@ class Transform(QtGui.QTransform):
} }
self.update() self.update()
def setFromMatrix4x4(self, m):
m = pg.Transform3D(m)
angle, axis = m.getRotation()
if angle != 0 and (axis[0] != 0 or axis[1] != 0 or axis[2] != 1):
raise Exception("Can only convert 4x4 matrix to 3x3 if rotation is around Z-axis.")
self._state = {
'pos': Point(m.getTranslation()),
'scale': Point(m.getScale()),
'angle': angle
}
self.update()
def translate(self, *args): def translate(self, *args):
"""Acceptable arguments are: """Acceptable arguments are:
x, y x, y

View File

@ -110,7 +110,9 @@ importAll('widgets', excludes=['MatplotlibWidget'])
from .imageview import * from .imageview import *
from .WidgetGroup import * from .WidgetGroup import *
from .Point import Point from .Point import Point
from .Vector import Vector
from .Transform import Transform from .Transform import Transform
from .Transform3D import Transform3D
from .functions import * from .functions import *
from .graphicsWindows import * from .graphicsWindows import *
from .SignalProxy import * from .SignalProxy import *

View File

@ -51,7 +51,7 @@ class Canvas(QtGui.QWidget):
#self.view.enableMouse() #self.view.enableMouse()
self.view.setAspectLocked(True) self.view.setAspectLocked(True)
self.view.invertY() #self.view.invertY()
grid = GridItem() grid = GridItem()
self.grid = CanvasItem(grid, name='Grid', movable=False) self.grid = CanvasItem(grid, name='Grid', movable=False)

View File

@ -7,14 +7,14 @@ class Dock(QtGui.QWidget, DockDrop):
sigStretchChanged = QtCore.Signal() sigStretchChanged = QtCore.Signal()
def __init__(self, name, area=None, size=(10, 10)): def __init__(self, name, area=None, size=(10, 10), widget=None, hideTitle=False, autoOrientation=True):
QtGui.QWidget.__init__(self) QtGui.QWidget.__init__(self)
DockDrop.__init__(self) DockDrop.__init__(self)
self.area = area self.area = area
self.label = DockLabel(name, self) self.label = DockLabel(name, self)
self.labelHidden = False self.labelHidden = False
self.moveLabel = True ## If false, the dock is no longer allowed to move the label. self.moveLabel = True ## If false, the dock is no longer allowed to move the label.
self.autoOrient = True self.autoOrient = autoOrientation
self.orientation = 'horizontal' self.orientation = 'horizontal'
#self.label.setAlignment(QtCore.Qt.AlignHCenter) #self.label.setAlignment(QtCore.Qt.AlignHCenter)
self.topLayout = QtGui.QGridLayout() self.topLayout = QtGui.QGridLayout()
@ -64,6 +64,12 @@ class Dock(QtGui.QWidget, DockDrop):
self.setStretch(*size) self.setStretch(*size)
if widget is not None:
self.addWidget(widget)
if hideTitle:
self.hideTitleBar()
def implements(self, name=None): def implements(self, name=None):
if name is None: if name is None:
return ['dock'] return ['dock']
@ -108,7 +114,7 @@ class Dock(QtGui.QWidget, DockDrop):
def setOrientation(self, o='auto', force=False): def setOrientation(self, o='auto', force=False):
#print self.name(), "setOrientation", o, force #print self.name(), "setOrientation", o, force
if o == 'auto': if o == 'auto' and self.autoOrient:
if self.container().type() == 'tab': if self.container().type() == 'tab':
o = 'horizontal' o = 'horizontal'
elif self.width() > self.height()*1.5: elif self.width() > self.height()*1.5:

View File

@ -9,21 +9,19 @@ import pyqtgraph as pg
app = QtGui.QApplication([]) app = QtGui.QApplication([])
## Create window with GraphicsView widget ## Create window with GraphicsView widget
win = QtGui.QMainWindow() w = pg.GraphicsView()
win.resize(800,800) w.show()
view = pg.GraphicsView() w.resize(800,800)
#view.useOpenGL(True)
win.setCentralWidget(view)
win.show()
## Allow mouse scale/pan view = pg.ViewBox()
view.enableMouse() w.setCentralItem(view)
## ..But lock the aspect ratio
## lock the aspect ratio
view.setAspectLocked(True) view.setAspectLocked(True)
## Create image item ## Create image item
img = pg.ImageItem(np.zeros((200,200))) img = pg.ImageItem(np.zeros((200,200)))
view.scene().addItem(img) view.addItem(img)
## Set initial view bounds ## Set initial view bounds
view.setRange(QtCore.QRectF(0, 0, 200, 200)) view.setRange(QtCore.QRectF(0, 0, 200, 200))

View File

@ -30,9 +30,7 @@ class ImageItem(GraphicsObject):
sigImageChanged = QtCore.Signal() sigImageChanged = QtCore.Signal()
sigRemoveRequested = QtCore.Signal(object) # self; emitted when 'remove' is selected from context menu
## performance gains from this are marginal, and it's rather unreliable.
useWeave = False
def __init__(self, image=None, **kargs): def __init__(self, image=None, **kargs):
""" """
@ -48,7 +46,6 @@ class ImageItem(GraphicsObject):
#self.clipMask = None #self.clipMask = None
self.paintMode = None self.paintMode = None
#self.useWeave = True
self.levels = None ## [min, max] or [[redMin, redMax], ...] self.levels = None ## [min, max] or [[redMin, redMax], ...]
self.lut = None self.lut = None
@ -56,6 +53,7 @@ class ImageItem(GraphicsObject):
#self.clipLevel = None #self.clipLevel = None
self.drawKernel = None self.drawKernel = None
self.border = None self.border = None
self.removable = False
if image is not None: if image is not None:
self.setImage(image, **kargs) self.setImage(image, **kargs)
@ -160,6 +158,9 @@ class ImageItem(GraphicsObject):
self.setCompositionMode(kargs['compositionMode']) self.setCompositionMode(kargs['compositionMode'])
if 'border' in kargs: if 'border' in kargs:
self.setBorder(kargs['border']) self.setBorder(kargs['border'])
if 'removable' in kargs:
self.removable = kargs['removable']
self.menu = None
def setRect(self, rect): def setRect(self, rect):
"""Scale and translate the image to fit within rect (must be a QRect or QRectF).""" """Scale and translate the image to fit within rect (must be a QRect or QRectF)."""
@ -264,7 +265,6 @@ class ImageItem(GraphicsObject):
argb, alpha = fn.makeARGB(self.image, lut=lut, levels=self.levels) argb, alpha = fn.makeARGB(self.image, lut=lut, levels=self.levels)
self.qimage = fn.makeQImage(argb, alpha) self.qimage = fn.makeQImage(argb, alpha)
#self.pixmap = QtGui.QPixmap.fromImage(self.qimage)
prof.finish() prof.finish()
@ -324,20 +324,71 @@ class ImageItem(GraphicsObject):
return 1,1 return 1,1
return br.width()/self.width(), br.height()/self.height() return br.width()/self.width(), br.height()/self.height()
def mousePressEvent(self, ev): #def mousePressEvent(self, ev):
#if self.drawKernel is not None and ev.button() == QtCore.Qt.LeftButton:
#self.drawAt(ev.pos(), ev)
#ev.accept()
#else:
#ev.ignore()
#def mouseMoveEvent(self, ev):
##print "mouse move", ev.pos()
#if self.drawKernel is not None:
#self.drawAt(ev.pos(), ev)
#def mouseReleaseEvent(self, ev):
#pass
def mouseDragEvent(self, ev):
if ev.button() != QtCore.Qt.LeftButton:
ev.ignore()
return
ev.accept()
self.drawAt(ev.pos(), ev)
def mouseClickEvent(self, ev):
if ev.button() == QtCore.Qt.RightButton:
if self.raiseContextMenu(ev):
ev.accept()
if self.drawKernel is not None and ev.button() == QtCore.Qt.LeftButton: if self.drawKernel is not None and ev.button() == QtCore.Qt.LeftButton:
self.drawAt(ev.pos(), ev) self.drawAt(ev.pos(), ev)
ev.accept()
else:
ev.ignore()
def mouseMoveEvent(self, ev): def raiseContextMenu(self, ev):
#print "mouse move", ev.pos() ## only raise menu if this terminal is removable
if self.drawKernel is not None: menu = self.getMenu()
self.drawAt(ev.pos(), ev) if menu is None:
return False
menu = self.scene().addParentContextMenus(self, menu, ev)
pos = ev.screenPos()
menu.popup(QtCore.QPoint(pos.x(), pos.y()))
return True
def getMenu(self):
if self.menu is None:
if not self.removable:
return None
self.menu = QtGui.QMenu()
self.menu.setTitle("Image")
remAct = QtGui.QAction("Remove image", self.menu)
remAct.triggered.connect(self.removeClicked)
self.menu.addAction(remAct)
self.menu.remAct = remAct
return self.menu
def hoverEvent(self, ev):
if not ev.isExit() and self.drawKernel is not None and ev.acceptDrags(QtCore.Qt.LeftButton):
ev.acceptClicks(QtCore.Qt.LeftButton) ## we don't use the click, but we also don't want anyone else to use it.
ev.acceptClicks(QtCore.Qt.RightButton)
#self.box.setBrush(fn.mkBrush('w'))
elif not ev.isExit() and self.removable:
ev.acceptClicks(QtCore.Qt.RightButton) ## accept context menu clicks
#else:
#self.box.setBrush(self.brush)
#self.update()
def mouseReleaseEvent(self, ev):
pass
def tabletEvent(self, ev): def tabletEvent(self, ev):
print(ev.device()) print(ev.device())
@ -364,20 +415,10 @@ class ImageItem(GraphicsObject):
ty[i] += dy1+dy2 ty[i] += dy1+dy2
sy[i] += dy1+dy2 sy[i] += dy1+dy2
#print sx
#print sy
#print tx
#print ty
#print self.image.shape
#print self.image[tx[0]:tx[1], ty[0]:ty[1]].shape
#print dk[sx[0]:sx[1], sy[0]:sy[1]].shape
ts = (slice(tx[0],tx[1]), slice(ty[0],ty[1])) ts = (slice(tx[0],tx[1]), slice(ty[0],ty[1]))
ss = (slice(sx[0],sx[1]), slice(sy[0],sy[1])) ss = (slice(sx[0],sx[1]), slice(sy[0],sy[1]))
#src = dk[sx[0]:sx[1], sy[0]:sy[1]]
#mask = self.drawMask[sx[0]:sx[1], sy[0]:sy[1]]
mask = self.drawMask mask = self.drawMask
src = dk src = dk
#print self.image[ts].shape, src.shape
if isinstance(self.drawMode, collections.Callable): if isinstance(self.drawMode, collections.Callable):
self.drawMode(dk, self.image, mask, ss, ts, ev) self.drawMode(dk, self.image, mask, ss, ts, ev)
@ -401,197 +442,5 @@ class ImageItem(GraphicsObject):
self.drawMode = mode self.drawMode = mode
self.drawMask = mask self.drawMask = mask
def removeClicked(self):
self.sigRemoveRequested.emit(self)
#def setImage(self, image=None, copy=True, autoRange=True, clipMask=None, white=None, black=None, axes=None):
#prof = debug.Profiler('ImageItem.updateImage 0x%x' %id(self), disabled=True)
##debug.printTrace()
#if axes is None:
#axh = {'x': 0, 'y': 1, 'c': 2}
#else:
#axh = axes
##print "Update image", black, white
#if white is not None:
#self.whiteLevel = white
#if black is not None:
#self.blackLevel = black
#gotNewData = False
#if image is None:
#if self.image is None:
#return
#else:
#gotNewData = True
#if self.image is None or image.shape != self.image.shape:
#self.prepareGeometryChange()
#if copy:
#self.image = image.view(np.ndarray).copy()
#else:
#self.image = image.view(np.ndarray)
##print " image max:", self.image.max(), "min:", self.image.min()
#prof.mark('1')
## Determine scale factors
#if autoRange or self.blackLevel is None:
#if self.image.dtype is np.ubyte:
#self.blackLevel = 0
#self.whiteLevel = 255
#else:
#self.blackLevel = self.image.min()
#self.whiteLevel = self.image.max()
##print "Image item using", self.blackLevel, self.whiteLevel
#if self.blackLevel != self.whiteLevel:
#scale = 255. / (self.whiteLevel - self.blackLevel)
#else:
#scale = 0.
#prof.mark('2')
### Recolor and convert to 8 bit per channel
## Try using weave, then fall back to python
#shape = self.image.shape
#black = float(self.blackLevel)
#white = float(self.whiteLevel)
#if black == 0 and white == 255 and self.image.dtype == np.ubyte:
#im = self.image
#elif self.image.dtype in [np.ubyte, np.uint16]:
## use lookup table instead
#npts = 2**(self.image.itemsize * 8)
#lut = self.getLookupTable(npts, black, white)
#im = lut[self.image]
#else:
#im = self.applyColorScaling(self.image, black, scale)
#prof.mark('3')
#try:
#im1 = np.empty((im.shape[axh['y']], im.shape[axh['x']], 4), dtype=np.ubyte)
#except:
#print im.shape, axh
#raise
#alpha = np.clip(int(255 * self.alpha), 0, 255)
#prof.mark('4')
## Fill image
#if im.ndim == 2:
#im2 = im.transpose(axh['y'], axh['x'])
#im1[..., 0] = im2
#im1[..., 1] = im2
#im1[..., 2] = im2
#im1[..., 3] = alpha
#elif im.ndim == 3: #color image
#im2 = im.transpose(axh['y'], axh['x'], axh['c'])
#if im2.shape[2] > 4:
#raise Exception("ImageItem got image with more than 4 color channels (shape is %s; axes are %s)" % (str(im.shape), str(axh)))
### [B G R A] Reorder colors
#order = [2,1,0,3] ## for some reason, the colors line up as BGR in the final image.
#for i in range(0, im.shape[axh['c']]):
#im1[..., order[i]] = im2[..., i]
### fill in unused channels with 0 or alpha
#for i in range(im.shape[axh['c']], 3):
#im1[..., i] = 0
#if im.shape[axh['c']] < 4:
#im1[..., 3] = alpha
#else:
#raise Exception("Image must be 2 or 3 dimensions")
##self.im1 = im1
## Display image
#prof.mark('5')
#if self.clipLevel is not None or clipMask is not None:
#if clipMask is not None:
#mask = clipMask.transpose()
#else:
#mask = (self.image < self.clipLevel).transpose()
#im1[..., 0][mask] *= 0.5
#im1[..., 1][mask] *= 0.5
#im1[..., 2][mask] = 255
#prof.mark('6')
##print "Final image:", im1.dtype, im1.min(), im1.max(), im1.shape
##self.ims = im1.tostring() ## Must be held in memory here because qImage won't do it for us :(
#prof.mark('7')
#try:
#buf = im1.data
#except AttributeError:
#im1 = np.ascontiguousarray(im1)
#buf = im1.data
#qimage = QtGui.QImage(buf, im1.shape[1], im1.shape[0], QtGui.QImage.Format_ARGB32)
#self.qimage = qimage
#self.qimage.data = im1
#self._pixmap = None
#prof.mark('8')
##self.pixmap = QtGui.QPixmap.fromImage(qimage)
#prof.mark('9')
###del self.ims
##self.item.setPixmap(self.pixmap)
#self.update()
#prof.mark('10')
#if gotNewData:
##self.emit(QtCore.SIGNAL('imageChanged'))
#self.sigImageChanged.emit()
#prof.finish()
#def getLookupTable(self, num, black, white):
#num = int(num)
#black = int(black)
#white = int(white)
#if white < black:
#b = black
#black = white
#white = b
#key = (num, black, white)
#lut = np.empty(num, dtype=np.ubyte)
#lut[:black] = 0
#rng = lut[black:white]
#try:
#rng[:] = np.linspace(0, 255, white-black)[:len(rng)]
#except:
#print key, rng.shape
#lut[white:] = 255
#return lut
#def applyColorScaling(self, img, offset, scale):
#try:
#if not ImageItem.useWeave:
#raise Exception('Skipping weave compile')
##sim = np.ascontiguousarray(self.image) ## should not be needed
#sim = img.reshape(img.size)
##sim.shape = sim.size
#im = np.empty(sim.shape, dtype=np.ubyte)
#n = im.size
#code = """
#for( int i=0; i<n; i++ ) {
#float a = (sim(i)-offset) * (float)scale;
#if( a > 255.0 )
#a = 255.0;
#else if( a < 0.0 )
#a = 0.0;
#im(i) = a;
#}
#"""
#weave.inline(code, ['sim', 'im', 'n', 'offset', 'scale'], type_converters=converters.blitz, compiler = 'gcc')
##sim.shape = shape
#im.shape = img.shape
#except:
#if ImageItem.useWeave:
#ImageItem.useWeave = False
##sys.excepthook(*sys.exc_info())
##print "=============================================================================="
##print "Weave compile failed, falling back to slower version."
##img.shape = shape
#im = ((img - offset) * scale).clip(0.,255.).astype(np.ubyte)
#return im

View File

@ -322,7 +322,7 @@ class PlotCurveItem(GraphicsObject):
pixels = self.pixelVectors() pixels = self.pixelVectors()
if pixels is None: if pixels == (None, None):
pixels = [Point(0,0), Point(0,0)] pixels = [Point(0,0), Point(0,0)]
xmin = x.min() - pixels[0].x() * lineWidth xmin = x.min() - pixels[0].x() * lineWidth
xmax = x.max() + pixels[0].x() * lineWidth xmax = x.max() + pixels[0].x() * lineWidth

View File

@ -22,7 +22,7 @@ class ScaleBar(UIGraphicsItem):
rect = self.boundingRect() rect = self.boundingRect()
unit = self.pixelSize() unit = self.pixelSize()
y = rect.bottom() + (rect.top()-rect.bottom()) * 0.02 y = rect.top() + (rect.bottom()-rect.top()) * 0.02
y1 = y + unit[1]*self._width y1 = y + unit[1]*self._width
x = rect.right() + (rect.left()-rect.right()) * 0.02 x = rect.right() + (rect.left()-rect.right()) * 0.02
x1 = x - self.size x1 = x - self.size

View File

@ -327,7 +327,8 @@ class ViewBox(GraphicsWidget):
changes[1] = yRange changes[1] = yRange
if len(changes) == 0: if len(changes) == 0:
raise Exception("Must specify at least one of rect, xRange, or yRange.") print rect
raise Exception("Must specify at least one of rect, xRange, or yRange. (gave rect=%s)" % str(type(rect)))
changed = [False, False] changed = [False, False]
for ax, range in changes.items(): for ax, range in changes.items():
@ -390,13 +391,17 @@ class ViewBox(GraphicsWidget):
""" """
self.setRange(xRange=[min, max], update=update, padding=padding) self.setRange(xRange=[min, max], update=update, padding=padding)
def autoRange(self, padding=0.02): def autoRange(self, padding=0.02, item=None):
""" """
Set the range of the view box to make all children visible. Set the range of the view box to make all children visible.
Note that this is not the same as enableAutoRange, which causes the view to Note that this is not the same as enableAutoRange, which causes the view to
automatically auto-range whenever its contents are changed. automatically auto-range whenever its contents are changed.
""" """
if item is None:
bounds = self.childrenBoundingRect() bounds = self.childrenBoundingRect()
else:
bounds = self.mapFromItemToView(item, item.boundingRect()).boundingRect()
if bounds is not None: if bounds is not None:
self.setRange(bounds, padding=padding) self.setRange(bounds, padding=padding)
@ -738,6 +743,19 @@ class ViewBox(GraphicsWidget):
return self.childGroup.mapToItem(item, obj) return self.childGroup.mapToItem(item, obj)
#return item.mapFromScene(self.mapViewToScene(obj)) #return item.mapFromScene(self.mapViewToScene(obj))
def mapViewToDevice(self, obj):
return self.mapToDevice(self.mapFromView(obj))
def mapDeviceToView(self, obj):
return self.mapToView(self.mapFromDevice(obj))
def viewPixelSize(self):
"""Return the (width, height) of a screen pixel in view coordinates."""
o = self.mapToView(Point(0,0))
px, py = [Point(self.mapToView(v) - o) for v in self.pixelVectors()]
return (px.length(), py.length())
def itemBoundingRect(self, item): def itemBoundingRect(self, item):
"""Return the bounding rect of the item in view coordinates""" """Return the bounding rect of the item in view coordinates"""
return self.mapSceneToView(item.sceneBoundingRect()).boundingRect() return self.mapSceneToView(item.sceneBoundingRect()).boundingRect()

View File

@ -175,7 +175,7 @@ class ImageView(QtGui.QWidget):
self.roiClicked() ## initialize roi plot to correct shape / visibility self.roiClicked() ## initialize roi plot to correct shape / visibility
def setImage(self, img, autoRange=True, autoLevels=True, levels=None, axes=None, xvals=None, pos=None, scale=None): def setImage(self, img, autoRange=True, autoLevels=True, levels=None, axes=None, xvals=None, pos=None, scale=None, transform=None):
""" """
Set the image to be displayed in the widget. Set the image to be displayed in the widget.
@ -284,6 +284,8 @@ class ImageView(QtGui.QWidget):
self.imageItem.scale(*scale) self.imageItem.scale(*scale)
if pos is not None: if pos is not None:
self.imageItem.setPos(*pos) self.imageItem.setPos(*pos)
if transform is not None:
self.imageItem.setTransform(transform)
prof.mark('6') prof.mark('6')
if autoRange: if autoRange:
@ -325,7 +327,7 @@ class ImageView(QtGui.QWidget):
image = self.getProcessedImage() image = self.getProcessedImage()
#self.ui.graphicsView.setRange(QtCore.QRectF(0, 0, image.shape[self.axes['x']], image.shape[self.axes['y']]), padding=0., lockAspect=True) #self.ui.graphicsView.setRange(QtCore.QRectF(0, 0, image.shape[self.axes['x']], image.shape[self.axes['y']]), padding=0., lockAspect=True)
self.view.setRange(self.imageItem.boundingRect(), padding=0.) self.view.autoRange() ##setRange(self.imageItem.viewBoundingRect(), padding=0.)
def getProcessedImage(self): def getProcessedImage(self):
"""Returns the image data after it has been processed by any normalization options in use.""" """Returns the image data after it has been processed by any normalization options in use."""

View File

@ -57,7 +57,7 @@ class CheckTable(QtGui.QWidget):
def removeRow(self, name): def removeRow(self, name):
row = self.rowNames.index(name) row = self.rowNames.index(name)
self.oldRows[name] = self.saveState['rows'][name] ## save for later self.oldRows[name] = self.saveState()['rows'][row] ## save for later
self.rowNames.pop(row) self.rowNames.pop(row)
for w in self.rowWidgets[row]: for w in self.rowWidgets[row]:
w.setParent(None) w.setParent(None)

View File

@ -12,6 +12,8 @@ class JoystickButton(QtGui.QPushButton):
self.setCheckable(True) self.setCheckable(True)
self.state = None self.state = None
self.setState(0,0) self.setState(0,0)
self.setFixedWidth(50)
self.setFixedHeight(50)
def mousePressEvent(self, ev): def mousePressEvent(self, ev):

View File

@ -47,6 +47,8 @@ class ValueLabel(QtGui.QLabel):
self.formatStr = text self.formatStr = text
self.update() self.update()
def setAverageTime(self, t):
self.averageTime = t
def averageValue(self): def averageValue(self):
return reduce(lambda a,b: a+b, [v[1] for v in self.values]) / float(len(self.values)) return reduce(lambda a,b: a+b, [v[1] for v in self.values]) / float(len(self.values))