Fix panning the x axis too fast, the right click zoom not working, and the mouse mode not propagating properly

This commit is contained in:
herodotus77 2021-10-11 17:33:45 -07:00
parent e06a4657ad
commit 415aaba36f
3 changed files with 32 additions and 15 deletions

View File

@ -135,10 +135,6 @@ class PlotItem(GraphicsWidget):
self.vb = viewBox
self.vb.sigStateChanged.connect(self.viewStateChanged)
# A set containing view boxes which are stacked underneath the top level view. These views will be needed
# in order to support multiple axes on the same plot. This set will remain empty if the plot has only one set of axes
self.stackedViews = weakref.WeakSet()
# Enable or disable plotItem menu
self.setMenuEnabled(enableMenu, None)
@ -147,7 +143,6 @@ class PlotItem(GraphicsWidget):
self.vb.sigRangeChanged.connect(self.sigRangeChanged)
self.vb.sigXRangeChanged.connect(self.sigXRangeChanged)
self.vb.sigYRangeChanged.connect(self.sigYRangeChanged)
self.vb.sigResized.connect(self.updateStackedViews)
self.layout.addItem(self.vb, 2, 1)
self.alpha = 1.0
@ -365,6 +360,7 @@ class PlotItem(GraphicsWidget):
view = ViewBox()
view.setXLink(self) # Link this view to the shared x-axis of this plot item TODO: Allow for multiple x axes
view.setMouseMode(self.vb.state['mouseMode']) # Ensure that mouse behavior is consistent between stacked views
view.isTopLevel = False
axis.linkToView(view)
if plotDataItem is not None:
view.addItem(plotDataItem)
@ -375,7 +371,7 @@ class PlotItem(GraphicsWidget):
# Rebuilding the layout of the plot item will put the new axis in the correct place
self.rebuildLayout()
self.updateStackedViews()
self.vb.updateStackedViews()
def addStackedView(self, view):
"""
@ -388,20 +384,12 @@ class PlotItem(GraphicsWidget):
The view to be added. Events handled by the top level view box will be passed through to this one as well
"""
self.stackedViews.add(view)
self.vb.stackedViews.add(view)
# These signals will be emitted by the top level view when it handles these events
self.vb.sigMouseDragged.connect(view.mouseDragEvent)
self.vb.sigMouseWheelZoomed.connect(view.wheelEvent)
self.vb.sigHistoryChanged.connect(view.scaleHistory)
def updateStackedViews(self):
"""
Callback for resizing stacked views when the geometry of their top level view changes
"""
for view in self.stackedViews:
view.setGeometry(self.vb.sceneBoundingRect())
view.linkedViewChanged(self.vb, view.XAxis)
def linkDataToAxis(self, plotDataItem, axisName):
"""
Links the input PlotDataItem to the axis with the given name. Raises an exception if that axis does not exist.

View File

@ -191,6 +191,12 @@ class ViewBox(GraphicsWidget):
self.childGroup = ChildGroup(self)
self.childGroup.itemsChangedListeners.append(self)
# A set containing view boxes which are stacked underneath the top level view. These views will be needed
# in order to support multiple axes on the same plot. This set will remain empty if the plot has only one set of axes
self.stackedViews = weakref.WeakSet()
self.isTopLevel = True # True if this view box is the top of any stacked view, false otherwise
self.sigResized.connect(self.updateStackedViews)
self.background = QtGui.QGraphicsRectItem(self.rect())
self.background.setParentItem(self)
self.background.setZValue(-1e6)
@ -1050,6 +1056,14 @@ class ViewBox(GraphicsWidget):
finally:
view.blockLink(False)
def updateStackedViews(self):
"""
Callback for resizing stacked views when the geometry of their top level view changes
"""
for view in self.stackedViews:
view.setGeometry(self.sceneBoundingRect())
view.linkedViewChanged(self, view.XAxis)
def screenGeometry(self):
"""return the screen geometry of the viewbox"""
v = self.getViewWidget()
@ -1281,6 +1295,10 @@ class ViewBox(GraphicsWidget):
self._resetTarget()
if x is not None or y is not None:
if not self.isTopLevel:
# Prevent each view in the stack from scrolling the same x axis at the same time
# TODO: Something better in the case of multiple x axes
x = None
self.translateBy(x=x, y=y)
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
if axis is None:
@ -1302,10 +1320,15 @@ class ViewBox(GraphicsWidget):
x = s[0] if mouseEnabled[0] == 1 else None
y = s[1] if mouseEnabled[1] == 1 else None
if not self.isTopLevel: # TODO: Like above, also something better than this
x = None
center = Point(tr.map(ev.buttonDownPos(QtCore.Qt.MouseButton.RightButton)))
self._resetTarget()
self.scaleBy(x=x, y=y, center=center)
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
if axis is None:
self.sigMouseDragged.emit(ev, axis)
def keyPressEvent(self, ev):
"""

View File

@ -219,9 +219,15 @@ class ViewBoxMenu(QtGui.QMenu):
def set3ButtonMode(self):
self.view().setLeftButtonAction('pan')
if len(self.view().stackedViews) > 0:
for view in self.view().stackedViews:
view.setLeftButtonAction('pan')
def set1ButtonMode(self):
self.view().setLeftButtonAction('rect')
if len(self.view().stackedViews) > 0:
for view in self.view().stackedViews:
view.setLeftButtonAction('rect')
def setViewList(self, views):
names = ['']