Merge pull request #514 from campagnola/viewbox-fix

Viewbox fix
This commit is contained in:
Luke Campagnola 2017-07-28 16:01:15 -07:00 committed by GitHub
commit 518c0b1d5c

View File

@ -85,7 +85,6 @@ class ViewBox(GraphicsWidget):
sigXRangeChanged = QtCore.Signal(object, object)
sigRangeChangedManually = QtCore.Signal(object)
sigRangeChanged = QtCore.Signal(object, object)
#sigActionPositionChanged = QtCore.Signal(object)
sigStateChanged = QtCore.Signal(object)
sigTransformChanged = QtCore.Signal(object)
sigResized = QtCore.Signal(object)
@ -128,8 +127,6 @@ class ViewBox(GraphicsWidget):
self.name = None
self.linksBlocked = False
self.addedItems = []
#self.gView = view
#self.showGrid = showGrid
self._matrixNeedsUpdate = True ## indicates that range has changed, but matrix update was deferred
self._autoRangeNeedsUpdate = True ## indicates auto-range needs to be recomputed.
@ -188,9 +185,6 @@ class ViewBox(GraphicsWidget):
self.background.setPen(fn.mkPen(None))
self.updateBackground()
#self.useLeftButtonPan = pyqtgraph.getConfigOption('leftButtonPan') # normally use left button to pan
# this also enables capture of keyPressEvents.
## Make scale box that is shown when dragging on the view
self.rbScaleBox = QtGui.QGraphicsRectItem(0, 0, 1, 1)
self.rbScaleBox.setPen(fn.mkPen((255,255,100), width=1))
@ -239,7 +233,6 @@ class ViewBox(GraphicsWidget):
ViewBox.updateAllViewLists()
sid = id(self)
self.destroyed.connect(lambda: ViewBox.forgetView(sid, name) if (ViewBox is not None and 'sid' in locals() and 'name' in locals()) else None)
#self.destroyed.connect(self.unregister)
def unregister(self):
"""
@ -288,16 +281,12 @@ class ViewBox(GraphicsWidget):
self.prepareForPaint()
self._lastScene = scene
def prepareForPaint(self):
#autoRangeEnabled = (self.state['autoRange'][0] is not False) or (self.state['autoRange'][1] is not False)
# don't check whether auto range is enabled here--only check when setting dirty flag.
if self._autoRangeNeedsUpdate: # and autoRangeEnabled:
self.updateAutoRange()
if self._matrixNeedsUpdate:
self.updateMatrix()
self.updateMatrix()
def getState(self, copy=True):
"""Return the current state of the ViewBox.
@ -326,7 +315,6 @@ class ViewBox(GraphicsWidget):
del state['linkedViews']
self.state.update(state)
#self.updateMatrix()
self.updateViewRange()
self.sigStateChanged.emit(self)
@ -353,12 +341,6 @@ class ViewBox(GraphicsWidget):
self.state['mouseMode'] = mode
self.sigStateChanged.emit(self)
#def toggleLeftAction(self, act): ## for backward compatibility
#if act.text() is 'pan':
#self.setLeftButtonAction('pan')
#elif act.text() is 'zoom':
#self.setLeftButtonAction('rect')
def setLeftButtonAction(self, mode='rect'): ## for backward compatibility
if mode.lower() == 'rect':
self.setMouseMode(ViewBox.RectMode)
@ -405,7 +387,6 @@ class ViewBox(GraphicsWidget):
if not ignoreBounds:
self.addedItems.append(item)
self.updateAutoRange()
#print "addItem:", item, item.boundingRect()
def removeItem(self, item):
"""Remove an item from this view."""
@ -562,10 +543,6 @@ class ViewBox(GraphicsWidget):
# If nothing has changed, we are done.
if any(changed):
#if update and self.matrixNeedsUpdate:
#self.updateMatrix(changed)
#return
self.sigStateChanged.emit(self)
# Update target rect for debugging
@ -581,21 +558,6 @@ class ViewBox(GraphicsWidget):
self._autoRangeNeedsUpdate = True
#self.updateAutoRange()
## Update view matrix only if requested
#if update:
#self.updateMatrix(changed)
## Otherwise, indicate that the matrix needs to be updated
#else:
#self.matrixNeedsUpdate = True
## Inform linked views that the range has changed <<This should be moved>>
#for ax, range in changes.items():
#link = self.linkedView(ax)
#if link is not None:
#link.linkedViewChanged(self, ax)
def setYRange(self, min, max, padding=None, update=True):
"""
Set the visible Y range of the view to [*min*, *max*].
@ -675,10 +637,6 @@ class ViewBox(GraphicsWidget):
for kwd in kwds:
if kwd not in allowed:
raise ValueError("Invalid keyword argument '%s'." % kwd)
#for kwd in ['xLimits', 'yLimits', 'minRange', 'maxRange']:
#if kwd in kwds and self.state['limits'][kwd] != kwds[kwd]:
#self.state['limits'][kwd] = kwds[kwd]
#update = True
for axis in [0,1]:
for mnmx in [0,1]:
kwd = [['xMin', 'xMax'], ['yMin', 'yMax']][axis][mnmx]
@ -694,9 +652,6 @@ class ViewBox(GraphicsWidget):
if update:
self.updateViewRange()
def scaleBy(self, s=None, center=None, x=None, y=None):
"""
@ -762,8 +717,6 @@ class ViewBox(GraphicsWidget):
y = vr.top()+y, vr.bottom()+y
if x is not None or y is not None:
self.setRange(xRange=x, yRange=y, padding=0)
def enableAutoRange(self, axis=None, enable=True, x=None, y=None):
"""
@ -773,11 +726,6 @@ class ViewBox(GraphicsWidget):
The argument *enable* may optionally be a float (0.0-1.0) which indicates the fraction of the data that should
be visible (this only works with items implementing a dataRange method, such as PlotDataItem).
"""
#print "autorange:", axis, enable
#if not enable:
#import traceback
#traceback.print_stack()
# support simpler interface:
if x is not None or y is not None:
if x is not None:
@ -813,10 +761,6 @@ class ViewBox(GraphicsWidget):
self.state['autoRange'][ax] = enable
self._autoRangeNeedsUpdate |= (enable is not False)
self.update()
#if needAutoRangeUpdate:
# self.updateAutoRange()
self.sigStateChanged.emit(self)
@ -828,6 +772,8 @@ class ViewBox(GraphicsWidget):
return self.state['autoRange'][:]
def setAutoPan(self, x=None, y=None):
"""Set whether automatic range will only pan (not scale) the view.
"""
if x is not None:
self.state['autoPan'][0] = x
if y is not None:
@ -836,6 +782,9 @@ class ViewBox(GraphicsWidget):
self.updateAutoRange()
def setAutoVisible(self, x=None, y=None):
"""Set whether automatic range uses only visible data when determining
the range to show.
"""
if x is not None:
self.state['autoVisibleOnly'][0] = x
if x is True:
@ -924,7 +873,6 @@ class ViewBox(GraphicsWidget):
"""Link this view's Y axis to another view. (see LinkView)"""
self.linkView(self.YAxis, view)
def linkView(self, axis, view):
"""
Link X or Y axes of two views and unlink any previously connected axes. *axis* must be ViewBox.XAxis or ViewBox.YAxis.
@ -1118,7 +1066,6 @@ class ViewBox(GraphicsWidget):
return
self.state['aspectLocked'] = ratio
if ratio != currentRatio: ## If this would change the current range, do that now
#self.setRange(0, self.state['viewRange'][0][0], self.state['viewRange'][0][1])
self.updateViewRange()
self.updateAutoRange()
@ -1130,12 +1077,9 @@ class ViewBox(GraphicsWidget):
Return the transform that maps from child(item in the childGroup) coordinates to local coordinates.
(This maps from inside the viewbox to outside)
"""
if self._matrixNeedsUpdate:
self.updateMatrix()
self.updateMatrix()
m = self.childGroup.transform()
#m1 = QtGui.QTransform()
#m1.translate(self.childGroup.pos().x(), self.childGroup.pos().y())
return m #*m1
return m
def mapToView(self, obj):
"""Maps from the local coordinates of the ViewBox to the coordinate system displayed inside the ViewBox"""
@ -1163,7 +1107,6 @@ class ViewBox(GraphicsWidget):
def mapFromViewToItem(self, item, obj):
"""Maps *obj* from view coordinates to the local coordinate system of *item*."""
return self.childGroup.mapToItem(item, obj)
#return item.mapFromScene(self.mapViewToScene(obj))
def mapViewToDevice(self, obj):
return self.mapToDevice(self.mapFromView(obj))
@ -1177,25 +1120,9 @@ class ViewBox(GraphicsWidget):
px, py = [Point(self.mapToView(v) - o) for v in self.pixelVectors()]
return (px.length(), py.length())
def itemBoundingRect(self, item):
"""Return the bounding rect of the item in view coordinates"""
return self.mapSceneToView(item.sceneBoundingRect()).boundingRect()
#def viewScale(self):
#vr = self.viewRect()
##print "viewScale:", self.range
#xd = vr.width()
#yd = vr.height()
#if xd == 0 or yd == 0:
#print "Warning: 0 range in view:", xd, yd
#return np.array([1,1])
##cs = self.canvas().size()
#cs = self.boundingRect()
#scale = np.array([cs.width() / xd, cs.height() / yd])
##print "view scale:", scale
#return scale
def wheelEvent(self, ev, axis=None):
mask = np.array(self.state['mouseEnabled'], dtype=np.float)
@ -1206,13 +1133,11 @@ class ViewBox(GraphicsWidget):
s = ((mask * 0.02) + 1) ** (ev.delta() * self.state['wheelScaleFactor']) # actual scaling factor
center = Point(fn.invertQTransform(self.childGroup.transform()).map(ev.pos()))
#center = ev.pos()
self._resetTarget()
self.scaleBy(s, center)
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
ev.accept()
def mouseClickEvent(self, ev):
if ev.button() == QtCore.Qt.RightButton and self.menuEnabled():
@ -1251,7 +1176,6 @@ class ViewBox(GraphicsWidget):
if ev.isFinish(): ## This is the final move in the drag; change the view scale now
#print "finish"
self.rbScaleBox.hide()
#ax = QtCore.QRectF(Point(self.pressPos), Point(self.mousePos))
ax = QtCore.QRectF(Point(ev.buttonDownPos(ev.button())), Point(pos))
ax = self.childGroup.mapRectFromParent(ax)
self.showAxRect(ax)
@ -1301,12 +1225,6 @@ class ViewBox(GraphicsWidget):
ctrl-- : moves backward in the zooming stack (if it exists)
"""
#print ev.key()
#print 'I intercepted a key press, but did not accept it'
## not implemented yet ?
#self.keypress.sigkeyPressEvent.emit()
ev.accept()
if ev.text() == '-':
self.scaleHistory(-1)
@ -1324,7 +1242,6 @@ class ViewBox(GraphicsWidget):
if ptr != self.axHistoryPointer:
self.axHistoryPointer = ptr
self.showAxRect(self.axHistory[ptr])
def updateScaleBox(self, p1, p2):
r = QtCore.QRectF(p1, p2)
@ -1338,14 +1255,6 @@ class ViewBox(GraphicsWidget):
self.setRange(ax.normalized()) # be sure w, h are correct coordinates
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
#def mouseRect(self):
#vs = self.viewScale()
#vr = self.state['viewRange']
## Convert positions from screen (view) pixel coordinates to axis coordinates
#ax = QtCore.QRectF(self.pressPos[0]/vs[0]+vr[0][0], -(self.pressPos[1]/vs[1]-vr[1][1]),
#(self.mousePos[0]-self.pressPos[0])/vs[0], -(self.mousePos[1]-self.pressPos[1])/vs[1])
#return(ax)
def allChildren(self, item=None):
"""Return a list of all children and grandchildren of this ViewBox"""
if item is None:
@ -1356,8 +1265,6 @@ class ViewBox(GraphicsWidget):
children.extend(self.allChildren(ch))
return children
def childrenBounds(self, frac=None, orthoRange=(None,None), items=None):
"""Return the bounding range of all children.
[[xmin, xmax], [ymin, ymax]]
@ -1380,8 +1287,6 @@ class ViewBox(GraphicsWidget):
useY = True
if hasattr(item, 'dataBounds'):
#bounds = self._itemBoundsCache.get(item, None)
#if bounds is None:
if frac is None:
frac = (1.0, 1.0)
xr = item.dataBounds(0, frac=frac[0], orthoRange=orthoRange[0])
@ -1414,9 +1319,6 @@ class ViewBox(GraphicsWidget):
itemBounds.append((bounds, useX, useY, pxPad))
#self._itemBoundsCache[item] = (bounds, useX, useY)
#else:
#bounds, useX, useY = bounds
else:
if int(item.flags() & item.ItemHasNoContents) > 0:
continue
@ -1425,8 +1327,6 @@ class ViewBox(GraphicsWidget):
bounds = self.mapFromItemToView(item, bounds).boundingRect()
itemBounds.append((bounds, True, True, 0))
#print itemBounds
## determine tentative new range
range = [None, None]
for bounds, useX, useY, px in itemBounds:
@ -1442,14 +1342,11 @@ class ViewBox(GraphicsWidget):
range[0] = [bounds.left(), bounds.right()]
profiler()
#print "range", range
## Now expand any bounds that have a pixel margin
## This must be done _after_ we have a good estimate of the new range
## to ensure that the pixel size is roughly accurate.
w = self.width()
h = self.height()
#print "w:", w, "h:", h
if w > 0 and range[0] is not None:
pxSize = (range[0][1] - range[0][0]) / w
for bounds, useX, useY, px in itemBounds:
@ -1585,9 +1482,9 @@ class ViewBox(GraphicsWidget):
self.sigYRangeChanged.emit(self, tuple(self.state['viewRange'][1]))
if any(changed):
self._matrixNeedsUpdate = True
self.sigRangeChanged.emit(self, self.state['viewRange'])
self.update()
self._matrixNeedsUpdate = True
# Inform linked views that the range has changed
for ax in [0, 1]:
@ -1598,6 +1495,9 @@ class ViewBox(GraphicsWidget):
link.linkedViewChanged(self, ax)
def updateMatrix(self, changed=None):
if not self._matrixNeedsUpdate:
return
## Make the childGroup's transform match the requested viewRange.
bounds = self.rect()
@ -1648,7 +1548,6 @@ class ViewBox(GraphicsWidget):
self.background.show()
self.background.setBrush(fn.mkBrush(bg))
def updateViewLists(self):
try:
self.window()
@ -1662,7 +1561,6 @@ class ViewBox(GraphicsWidget):
## make a sorted list of all named views
nv = list(ViewBox.NamedViews.values())
#print "new view list:", nv
sortList(nv, cmpViews) ## see pyqtgraph.python2_3.sortList
if self in nv:
@ -1676,16 +1574,11 @@ class ViewBox(GraphicsWidget):
for v in nv:
if link == v.name:
self.linkView(ax, v)
#print "New view list:", nv
#print "linked views:", self.state['linkedViews']
@staticmethod
def updateAllViewLists():
#print "Update:", ViewBox.AllViews.keys()
#print "Update:", ViewBox.NamedViews.keys()
for v in ViewBox.AllViews:
v.updateViewLists()
@staticmethod
def forgetView(vid, name):
@ -1766,4 +1659,5 @@ class ViewBox(GraphicsWidget):
self.scene().removeItem(self.locateGroup)
self.locateGroup = None
from .ViewBoxMenu import ViewBoxMenu