diff --git a/pyqtgraph/graphicsItems/AxisItem.py b/pyqtgraph/graphicsItems/AxisItem.py index 8d8ed11b..d5b09915 100644 --- a/pyqtgraph/graphicsItems/AxisItem.py +++ b/pyqtgraph/graphicsItems/AxisItem.py @@ -148,7 +148,31 @@ class AxisItem(GraphicsWidget): self.setScale() def setLabel(self, text=None, units=None, unitPrefix=None, **args): - """Set the text displayed adjacent to the axis.""" + """Set the text displayed adjacent to the axis. + + ============= ============================================================= + Arguments + text The text (excluding units) to display on the label for this + axis. + units The units for this axis. Units should generally be given + without any scaling prefix (eg, 'V' instead of 'mV'). The + scaling prefix will be automatically prepended based on the + range of data displayed. + **args All extra keyword arguments become CSS style options for + the tag which will surround the axis label and units. + ============= ============================================================= + + The final text generated for the label will look like:: + + {text} (prefix{units}) + + Each extra keyword argument will become a CSS option in the above template. + For example, you can set the font size and color of the label:: + + labelStyle = {'color': '#FFF', 'font-size': '14pt'} + axis.setLabel('label text', units='V', **labelStyle) + + """ if text is not None: self.labelText = text self.showLabel() diff --git a/pyqtgraph/graphicsItems/LinearRegionItem.py b/pyqtgraph/graphicsItems/LinearRegionItem.py index 0b44c815..a35e8efc 100644 --- a/pyqtgraph/graphicsItems/LinearRegionItem.py +++ b/pyqtgraph/graphicsItems/LinearRegionItem.py @@ -245,7 +245,7 @@ class LinearRegionItem(UIGraphicsItem): def hoverEvent(self, ev): - if (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton): + if self.movable and (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton): self.setMouseHover(True) else: self.setMouseHover(False) diff --git a/pyqtgraph/graphicsItems/ScatterPlotItem.py b/pyqtgraph/graphicsItems/ScatterPlotItem.py index 32fac052..45adcf4d 100644 --- a/pyqtgraph/graphicsItems/ScatterPlotItem.py +++ b/pyqtgraph/graphicsItems/ScatterPlotItem.py @@ -599,7 +599,7 @@ class ScatterPlotItem(GraphicsObject): self.invalidate() def dataBounds(self, ax, frac=1.0, orthoRange=None): - if frac >= 1.0 and self.bounds[ax] is not None: + if frac >= 1.0 and orthoRange is None and self.bounds[ax] is not None: return self.bounds[ax] #self.prepareGeometryChange() diff --git a/pyqtgraph/graphicsItems/ViewBox/ViewBox.py b/pyqtgraph/graphicsItems/ViewBox/ViewBox.py index f5aa03b8..8b4ba2af 100644 --- a/pyqtgraph/graphicsItems/ViewBox/ViewBox.py +++ b/pyqtgraph/graphicsItems/ViewBox/ViewBox.py @@ -138,7 +138,7 @@ class ViewBox(GraphicsWidget): self.rbScaleBox.setPen(fn.mkPen((255,255,100), width=1)) self.rbScaleBox.setBrush(fn.mkBrush(255,255,0,100)) self.rbScaleBox.hide() - self.addItem(self.rbScaleBox) + self.addItem(self.rbScaleBox, ignoreBounds=True) self.axHistory = [] # maintain a history of zoom locations self.axHistoryPointer = -1 # pointer into the history. Allows forward/backward movement, not just "undo" diff --git a/pyqtgraph/parametertree/Parameter.py b/pyqtgraph/parametertree/Parameter.py index c8ed4902..f7da0dbe 100644 --- a/pyqtgraph/parametertree/Parameter.py +++ b/pyqtgraph/parametertree/Parameter.py @@ -88,9 +88,10 @@ class Parameter(QtCore.QObject): @staticmethod def create(**opts): """ - Create a new Parameter (or subclass) instance using opts['type'] to select the - appropriate class. + Static method that creates a new Parameter (or subclass) instance using + opts['type'] to select the appropriate class. + All options are passed directly to the new Parameter's __init__ method. Use registerParameterType() to add new class types. """ typ = opts.get('type', None) @@ -101,6 +102,41 @@ class Parameter(QtCore.QObject): return cls(**opts) def __init__(self, **opts): + """ + Initialize a Parameter object. Although it is rare to directly create a + Parameter instance, the options available to this method are also allowed + by most Parameter subclasses. + + ================= ========================================================= + Keyword Arguments + name The name to give this Parameter. This is the name that + will appear in the left-most column of a ParameterTree + for this Parameter. + value The value to initially assign to this Parameter. + default The default value for this Parameter (most Parameters + provide an option to 'reset to default'). + children A list of children for this Parameter. Children + may be given either as a Parameter instance or as a + dictionary to pass to Parameter.create(). In this way, + it is possible to specify complex hierarchies of + Parameters from a single nested data structure. + readonly If True, the user will not be allowed to edit this + Parameter. (default=False) + enabled If False, any widget(s) for this parameter will appear + disabled. (default=True) + visible If False, the Parameter will not appear when displayed + in a ParameterTree. (default=True) + renamable If True, the user may rename this Parameter. + (default=False) + removable If True, the user may remove this Parameter. + (default=False) + expanded If True, the Parameter will appear expanded when + displayed in a ParameterTree (its children will be + visible). (default=True) + ================= ========================================================= + """ + + QtCore.QObject.__init__(self) self.opts = { @@ -111,6 +147,7 @@ class Parameter(QtCore.QObject): 'renamable': False, 'removable': False, 'strictNaming': False, # forces name to be usable as a python variable + 'expanded': True, #'limits': None, ## This is a bad plan--each parameter type may have a different data type for limits. } self.opts.update(opts) @@ -148,6 +185,7 @@ class Parameter(QtCore.QObject): #self.watchParam(self) ## emit treechange signals if our own state changes def name(self): + """Return the name of this Parameter.""" return self.opts['name'] def setName(self, name): @@ -165,6 +203,7 @@ class Parameter(QtCore.QObject): return name def type(self): + """Return the type string for this Parameter.""" return self.opts['type'] def isType(self, typ): @@ -197,8 +236,10 @@ class Parameter(QtCore.QObject): return path def setValue(self, value, blockSignal=None): - ## return the actual value that was set - ## (this may be different from the value that was requested) + """ + Set the value of this Parameter; return the actual value that was set. + (this may be different from the value that was requested) + """ try: if blockSignal is not None: self.sigValueChanged.disconnect(blockSignal) @@ -213,6 +254,9 @@ class Parameter(QtCore.QObject): return value def value(self): + """ + Return the value of this Parameter. + """ return self.opts['value'] def getValues(self): @@ -352,9 +396,12 @@ class Parameter(QtCore.QObject): return not self.opts.get('readonly', False) def setWritable(self, writable=True): + """Set whether this Parameter should be editable by the user. (This is + exactly the opposite of setReadonly).""" self.setOpts(readonly=not writable) def setReadonly(self, readonly=True): + """Set whether this Parameter's value may be edited by the user.""" self.setOpts(readonly=readonly) def setOpts(self, **opts): @@ -362,7 +409,10 @@ class Parameter(QtCore.QObject): Set any arbitrary options on this parameter. The exact behavior of this function will depend on the parameter type, but most parameters will accept a common set of options: value, name, limits, - default, readonly, removable, renamable, visible, and enabled. + default, readonly, removable, renamable, visible, enabled, and expanded. + + See :func:`Parameter.__init__ ` + for more information on default options. """ changed = OrderedDict() for k in opts: @@ -390,7 +440,10 @@ class Parameter(QtCore.QObject): self.emitTreeChanges() def makeTreeItem(self, depth): - """Return a TreeWidgetItem suitable for displaying/controlling the content of this parameter. + """ + Return a TreeWidgetItem suitable for displaying/controlling the content of + this parameter. This is called automatically when a ParameterTree attempts + to display this Parameter. Most subclasses will want to override this function. """ if hasattr(self, 'itemClass'): @@ -424,7 +477,8 @@ class Parameter(QtCore.QObject): """ Insert a new child at pos. If pos is a Parameter, then insert at the position of that Parameter. - If child is a dict, then a parameter is constructed as Parameter(\*\*child) + If child is a dict, then a parameter is constructed using + :func:`Parameter.create `. """ if isinstance(child, dict): child = Parameter.create(**child) @@ -476,6 +530,7 @@ class Parameter(QtCore.QObject): return self.childs[:] def hasChildren(self): + """Return True if this Parameter has children.""" return len(self.childs) > 0 def parentChanged(self, parent): @@ -553,6 +608,10 @@ class Parameter(QtCore.QObject): def __getattr__(self, attr): ## Leaving this undocumented because I might like to remove it in the future.. #print type(self), attr + import traceback + traceback.print_stack() + print "Warning: Use of Parameter.subParam is deprecated. Use Parameter.param(name) instead." + if 'names' not in self.__dict__: raise AttributeError(attr) if attr in self.names: @@ -582,36 +641,6 @@ class Parameter(QtCore.QObject): self.sigOptionsChanged.emit(self, {'visible': s}) - #def monitorChildren(self): - #if self.monitoringChildren: - #raise Exception("Already monitoring children.") - #self.watchParam(self) - #self.monitoringChildren = True - - #def watchParam(self, param): - #param.sigChildAdded.connect(self.grandchildAdded) - #param.sigChildRemoved.connect(self.grandchildRemoved) - #param.sigStateChanged.connect(self.grandchildChanged) - #for ch in param: - #self.watchParam(ch) - - #def unwatchParam(self, param): - #param.sigChildAdded.disconnect(self.grandchildAdded) - #param.sigChildRemoved.disconnect(self.grandchildRemoved) - #param.sigStateChanged.disconnect(self.grandchildChanged) - #for ch in param: - #self.unwatchParam(ch) - - #def grandchildAdded(self, parent, child): - #self.watchParam(child) - - #def grandchildRemoved(self, parent, child): - #self.unwatchParam(child) - - #def grandchildChanged(self, param, change, data): - ##self.sigTreeStateChanged.emit(self, param, change, data) - #self.emitTreeChange((param, change, data)) - def treeChangeBlocker(self): """ Return an object that can be used to temporarily block and accumulate diff --git a/pyqtgraph/ptime.py b/pyqtgraph/ptime.py index ac61f57f..1de8282f 100644 --- a/pyqtgraph/ptime.py +++ b/pyqtgraph/ptime.py @@ -20,7 +20,7 @@ def unixTime(): """Return the current time in seconds with high precision (unix version, use Manager.time() to stay platform independent).""" return systime.time() -if 'win' in sys.platform: +if sys.platform.startswith('win'): cstart = systime.clock() ### Required to start the clock in windows START_TIME = systime.time() - cstart diff --git a/pyqtgraph/widgets/RemoteGraphicsView.py b/pyqtgraph/widgets/RemoteGraphicsView.py index 3722e87e..2dd1fe9b 100644 --- a/pyqtgraph/widgets/RemoteGraphicsView.py +++ b/pyqtgraph/widgets/RemoteGraphicsView.py @@ -32,7 +32,7 @@ class RemoteGraphicsView(QtGui.QWidget): self.setMouseTracking(True) self.shm = None shmFileName = self._view.shmFileName() - if 'win' in sys.platform: + if sys.platform.startswith('win'): self.shmtag = shmFileName else: self.shmFile = open(shmFileName, 'r') @@ -60,7 +60,7 @@ class RemoteGraphicsView(QtGui.QWidget): if self.shm is None or self.shm.size != size: if self.shm is not None: self.shm.close() - if 'win' in sys.platform: + if sys.platform.startswith('win'): self.shmtag = newfile ## on windows, we create a new tag for every resize self.shm = mmap.mmap(-1, size, self.shmtag) ## can't use tmpfile on windows because the file can only be opened once. else: @@ -119,7 +119,7 @@ class Renderer(GraphicsView): def __init__(self, *args, **kwds): ## Create shared memory for rendered image - if 'win' in sys.platform: + if sys.platform.startswith('win'): self.shmtag = "pyqtgraph_shmem_" + ''.join([chr((random.getrandbits(20)%25) + 97) for i in range(20)]) self.shm = mmap.mmap(-1, mmap.PAGESIZE, self.shmtag) # use anonymous mmap on windows else: @@ -138,11 +138,11 @@ class Renderer(GraphicsView): def close(self): self.shm.close() - if 'win' not in sys.platform: + if sys.platform.startswith('win'): self.shmFile.close() def shmFileName(self): - if 'win' in sys.platform: + if sys.platform.startswith('win'): return self.shmtag else: return self.shmFile.name @@ -164,7 +164,7 @@ class Renderer(GraphicsView): return size = self.width() * self.height() * 4 if size > self.shm.size(): - if 'win' in sys.platform: + if sys.platform.startswith('win'): ## windows says "WindowsError: [Error 87] the parameter is incorrect" if we try to resize the mmap self.shm.close() ## it also says (sometimes) 'access is denied' if we try to reuse the tag.