Skip to content

Commit 804b503

Browse files
committed
Limit crosshair to axes region
1 parent fe0fbd0 commit 804b503

File tree

2 files changed

+35
-16
lines changed

2 files changed

+35
-16
lines changed

lib/matplotlib/backends/backend_qt.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import namedtuple
12
import functools
23
import os
34
import sys
@@ -213,6 +214,9 @@ def _timer_stop(self):
213214
self._timer.stop()
214215

215216

217+
Crosshair = namedtuple('Crosshair', 'x, y, x0, x1, y0, y1')
218+
219+
216220
class FigureCanvasQT(FigureCanvasBase, QtWidgets.QWidget):
217221
required_interactive_framework = "qt"
218222
_timer_cls = TimerQT
@@ -231,6 +235,7 @@ class FigureCanvasQT(FigureCanvasBase, QtWidgets.QWidget):
231235
def __init__(self, figure=None):
232236
_create_qApp()
233237
super().__init__(figure=figure)
238+
self._crosshair = None
234239

235240
self._draw_pending = False
236241
self._is_drawing = False
@@ -239,7 +244,6 @@ def __init__(self, figure=None):
239244

240245
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_OpaquePaintEvent)
241246
self.setMouseTracking(True)
242-
self.mouse_xy = (0, 0)
243247
self.resize(*self.get_width_height())
244248

245249
palette = QtGui.QPalette(QtGui.QColor("white"))
@@ -306,6 +310,21 @@ def mouseEventCoords(self, pos=None):
306310
y = self.figure.bbox.height / self.device_pixel_ratio - pos.y()
307311
return x * self.device_pixel_ratio, y * self.device_pixel_ratio
308312

313+
def _update_crosshair(self, x, y):
314+
previous_crosshair = self._crosshair
315+
ax = self.inaxes((x, y))
316+
if ax is None:
317+
self._crosshair = None
318+
else:
319+
bbox = ax.get_position() # in figure coords
320+
x0 = int(bbox.x0 * self.width())
321+
x1 = int(bbox.x1 * self.width())
322+
y0 = int((1 - bbox.y0) * self.height())
323+
y1 = int((1 - bbox.y1) * self.height())
324+
self._crosshair = Crosshair(x, y, x0, x1, y0, y1)
325+
needs_repaint = previous_crosshair is not None or self._crosshair is not None
326+
return needs_repaint
327+
309328
def enterEvent(self, event):
310329
# Force querying of the modifiers, as the cached modifier state can
311330
# have been invalidated while the window was out of focus.
@@ -345,10 +364,12 @@ def mouseDoubleClickEvent(self, event):
345364
def mouseMoveEvent(self, event):
346365
if self.figure is None:
347366
return
348-
self.mouse_xy = self.mouseEventCoords(event)
349-
self.repaint()
367+
mouse_xy = self.mouseEventCoords(event)
368+
needs_repaint = self._update_crosshair(*mouse_xy)
369+
if needs_repaint:
370+
self.repaint()
350371
MouseEvent("motion_notify_event", self,
351-
*self.mouse_xy,
372+
*mouse_xy,
352373
buttons=self._mpl_buttons(event.buttons()),
353374
modifiers=self._mpl_modifiers(),
354375
guiEvent=event)._process()

lib/matplotlib/backends/backend_qtagg.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,16 @@ def paintEvent(self, event):
6969

7070
self._draw_rect_callback(painter)
7171

72-
figx = self.mouse_xy[0] / rect.width()
73-
figy = 1 - self.mouse_xy[1] / rect.height()
74-
x0 = rect.left()
75-
x1 = rect.left() + rect.width()
76-
y0 = rect.top()
77-
y1 = rect.top() + rect.height()
78-
x = rect.left() + int(figx * rect.width())
79-
y = rect.top() + int(figy * rect.height())
80-
painter.setPen(QtGui.QPen(QtCore.Qt.GlobalColor.red))
81-
painter.drawLine(x0, y, x1, y)
82-
painter.drawLine(x, y0, x, y1)
83-
72+
if self._crosshair is not None:
73+
x = self._crosshair.x
74+
y = rect.height() - int(self._crosshair.y)
75+
x0 = rect.left() + self._crosshair.x0
76+
x1 = rect.left() + self._crosshair.x1
77+
y0 = rect.top() + self._crosshair.y0
78+
y1 = rect.top() + self._crosshair.y1
79+
painter.setPen(QtGui.QPen(QtCore.Qt.GlobalColor.red))
80+
painter.drawLine(x0, y, x1, y)
81+
painter.drawLine(x, y0, x, y1)
8482
finally:
8583
painter.end()
8684

0 commit comments

Comments
 (0)