From 415aaba36f931c4ecd9edecc36eb80a9cd3cf35a Mon Sep 17 00:00:00 2001 From: herodotus77 Date: Mon, 11 Oct 2021 17:33:45 -0700 Subject: [PATCH] Fix panning the x axis too fast, the right click zoom not working, and the mouse mode not propagating properly --- pyqtgraph/graphicsItems/PlotItem/PlotItem.py | 18 +++------------ pyqtgraph/graphicsItems/ViewBox/ViewBox.py | 23 +++++++++++++++++++ .../graphicsItems/ViewBox/ViewBoxMenu.py | 6 +++++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/pyqtgraph/graphicsItems/PlotItem/PlotItem.py b/pyqtgraph/graphicsItems/PlotItem/PlotItem.py index 7109f45a..764e9d5f 100644 --- a/pyqtgraph/graphicsItems/PlotItem/PlotItem.py +++ b/pyqtgraph/graphicsItems/PlotItem/PlotItem.py @@ -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. diff --git a/pyqtgraph/graphicsItems/ViewBox/ViewBox.py b/pyqtgraph/graphicsItems/ViewBox/ViewBox.py index 568b8fdd..1d1bf09a 100644 --- a/pyqtgraph/graphicsItems/ViewBox/ViewBox.py +++ b/pyqtgraph/graphicsItems/ViewBox/ViewBox.py @@ -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): """ diff --git a/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py b/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py index 9e955c94..4165b815 100644 --- a/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py +++ b/pyqtgraph/graphicsItems/ViewBox/ViewBoxMenu.py @@ -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 = ['']