Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4bdbc54

Browse files
committed
task 2 - added hover backend implementation & tk specific label
1 parent e2b2c0e commit 4bdbc54

File tree

5 files changed

+79
-17
lines changed

5 files changed

+79
-17
lines changed

doc/api/artist_api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ Interactive
4444
Artist.pickable
4545
Artist.set_picker
4646
Artist.get_picker
47+
Artist.hover
48+
Artist.hoverable
49+
Artist.set_hover
50+
Artist.get_hover
4751

4852
Clipping
4953
--------

lib/matplotlib/artist.py

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -596,34 +596,58 @@ def get_picker(self):
596596
"""
597597
return self._picker
598598

599+
def hoverable(self):
600+
"""
601+
Return whether the artist is hoverable.
602+
603+
See Also
604+
--------
605+
set_hover, get_hover, hover
606+
"""
607+
return self.figure is not None and self._hover is not None
608+
609+
def hover(self, mouseevent):
610+
"""
611+
Process a hover event.
612+
613+
Each child artist will fire a hover event if *mouseevent* is over
614+
the artist and the artist has hover set.
615+
616+
See Also
617+
--------
618+
set_hover, get_hover, hoverable
619+
"""
620+
from .backend_bases import HoverEvent # Circular import.
621+
# Hover self
622+
if self.hoverable():
623+
hoverer = self.get_hover()
624+
inside, prop = self.contains(mouseevent)
625+
if inside:
626+
HoverEvent("hover_event", self.figure.canvas,
627+
mouseevent, self, **prop)._process()
628+
629+
# Pick children
630+
for a in self.get_children():
631+
# make sure the event happened in the same Axes
632+
ax = getattr(a, 'axes', None)
633+
if (mouseevent.inaxes is None or ax is None
634+
or mouseevent.inaxes == ax):
635+
a.hover(mouseevent)
636+
599637
def set_hover(self, hover):
600638
"""
601639
Define the hover status of the artist.
602640
603641
Parameters
604642
----------
605-
hover : None or bool or float or callable
643+
hover : None or bool
606644
This can be one of the following:
607645
608646
- *None*: Hover is disabled for this artist (default).
609647
610648
- A boolean: If *True* then hover will be enabled and the
611649
artist will fire a hover event if the mouse event is hovering over
612650
the artist.
613-
614-
- A float: If hover is a number it is interpreted as an
615-
epsilon tolerance in points and the artist will fire
616-
off an event if its data is within epsilon of the mouse
617-
event. For some artists like lines and patch collections,
618-
the artist may provide additional data to the hover event
619-
that is generated, e.g., the indices of the data within
620-
epsilon of the hover event
621-
622-
- A function: If hover is callable, it is a user supplied
623-
function which determines whether the artist is hit by the
624-
mouse event to determine the hit test. if the mouse event
625-
is over the artist, return *hit=True* and props is a dictionary of
626-
properties you want added to the HoverEvent attributes.
627651
"""
628652
self._hover = hover
629653

lib/matplotlib/backend_bases.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,8 @@ class FigureCanvasBase:
17441744
'figure_leave_event',
17451745
'axes_enter_event',
17461746
'axes_leave_event',
1747-
'close_event'
1747+
'close_event',
1748+
'hover_event'
17481749
]
17491750

17501751
fixed_dpi = None
@@ -2295,7 +2296,8 @@ def mpl_connect(self, s, func):
22952296
- 'figure_leave_event',
22962297
- 'axes_enter_event',
22972298
- 'axes_leave_event'
2298-
- 'close_event'.
2299+
- 'close_event'
2300+
- 'hover_event'
22992301
23002302
func : callable
23012303
The callback function to be executed, which must have the
@@ -3007,9 +3009,19 @@ def _mouse_event_to_message(event):
30073009
return ""
30083010

30093011
def mouse_move(self, event):
3012+
from .patches import Rectangle
30103013
self._update_cursor(event)
30113014
self.set_message(self._mouse_event_to_message(event))
30123015

3016+
if callable(getattr(self, 'set_hover_message', None)):
3017+
for a in self.canvas.figure.findobj(match=lambda x: not isinstance(x, Rectangle), include_self=False):
3018+
inside, prop = a.contains(event)
3019+
if inside:
3020+
self.set_hover_message(self._mouse_event_to_message(event))
3021+
else:
3022+
self.set_hover_message("")
3023+
break
3024+
30133025
def _zoom_pan_handler(self, event):
30143026
if self.mode == _Mode.PAN:
30153027
if event.name == "button_press_event":

lib/matplotlib/backends/_backend_tk.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,12 @@ def __init__(self, canvas, window=None, *, pack_toolbar=True):
649649
justify=tk.RIGHT)
650650
self._message_label.pack(side=tk.RIGHT)
651651

652+
self.hover_message = tk.StringVar(master=self)
653+
self._hover_label = tk.Label(master=self, font=self._label_font,
654+
textvariable=self.hover_message,
655+
justify=tk.RIGHT)
656+
self._hover_label.pack(side=tk.RIGHT)
657+
652658
NavigationToolbar2.__init__(self, canvas)
653659
if pack_toolbar:
654660
self.pack(side=tk.BOTTOM, fill=tk.X)
@@ -700,6 +706,9 @@ def zoom(self, *args):
700706
def set_message(self, s):
701707
self.message.set(s)
702708

709+
def set_hover_message(self, s):
710+
self.hover_message.set(s)
711+
703712
def draw_rubberband(self, event, x0, y0, x1, y1):
704713
# Block copied from remove_rubberband for backend_tools convenience.
705714
if self.canvas._rubberband_rect_white:
@@ -976,6 +985,12 @@ def __init__(self, toolmanager, window=None):
976985
self._message_label = tk.Label(master=self, font=self._label_font,
977986
textvariable=self._message)
978987
self._message_label.pack(side=tk.RIGHT)
988+
989+
self._hover_message = tk.StringVar(master=self)
990+
self._hover_label = tk.Label(master=self, font=self._label_font,
991+
textvariable=self._hover_message)
992+
self._hover_label.pack(side=tk.RIGHT)
993+
979994
self._toolitems = {}
980995
self.pack(side=tk.TOP, fill=tk.X)
981996
self._groups = {}
@@ -1032,6 +1047,8 @@ def remove_toolitem(self, name):
10321047
def set_message(self, s):
10331048
self._message.set(s)
10341049

1050+
def set_hover_message(self, s):
1051+
self._hover_message.set(s)
10351052

10361053
@backend_tools._register_tool_class(FigureCanvasTk)
10371054
class SaveFigureTk(backend_tools.SaveFigureBase):

lib/matplotlib/figure.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,7 @@ def __init__(self,
25192519
]
25202520
self._button_pick_id = connect('button_press_event', self.pick)
25212521
self._scroll_pick_id = connect('scroll_event', self.pick)
2522+
self._hover_id = connect('motion_notify_event', self.hover)
25222523

25232524
if figsize is None:
25242525
figsize = mpl.rcParams['figure.figsize']
@@ -2566,6 +2567,10 @@ def pick(self, mouseevent):
25662567
if not self.canvas.widgetlock.locked():
25672568
super().pick(mouseevent)
25682569

2570+
def hover(self, mouseevent):
2571+
if not self.canvas.widgetlock.locked():
2572+
super().hover(mouseevent)
2573+
25692574
def _check_layout_engines_compat(self, old, new):
25702575
"""
25712576
Helper for set_layout engine

0 commit comments

Comments
 (0)