""" Behaviors/Hover =============== .. rubric:: Changing when the mouse is on the widget. To apply hover behavior, you must create a new class that is inherited from the widget to which you apply the behavior and from the :attr:`HoverBehavior` class. In `KV file`: .. code-block:: kv In `python file`: .. code-block:: python class HoverItem(MDBoxLayout, ThemableBehavior, HoverBehavior): '''Custom item implementing hover behavior.''' After creating a class, you must define two methods for it: :attr:`HoverBehavior.on_enter` and :attr:`HoverBehavior.on_leave`, which will be automatically called when the mouse cursor is over the widget and when the mouse cursor goes beyond the widget. .. code-block:: python from kivy.lang import Builder from kivymd.app import MDApp from kivymd.uix.behaviors import HoverBehavior from kivymd.uix.boxlayout import MDBoxLayout from kivymd.theming import ThemableBehavior KV = ''' Screen MDBoxLayout: id: box pos_hint: {'center_x': .5, 'center_y': .5} size_hint: .8, .8 md_bg_color: app.theme_cls.bg_darkest ''' class HoverItem(MDBoxLayout, ThemableBehavior, HoverBehavior): '''Custom item implementing hover behavior.''' def on_enter(self, *args): '''The method will be called when the mouse cursor is within the borders of the current widget.''' self.md_bg_color = (1, 1, 1, 1) def on_leave(self, *args): '''The method will be called when the mouse cursor goes beyond the borders of the current widget.''' self.md_bg_color = self.theme_cls.bg_darkest class Test(MDApp): def build(self): self.screen = Builder.load_string(KV) for i in range(5): self.screen.ids.box.add_widget(HoverItem()) return self.screen Test().run() .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/hover-behavior.gif :width: 250 px :align: center """ __all__ = ("HoverBehavior",) from kivy.core.window import Window from kivy.factory import Factory from kivy.properties import BooleanProperty, ObjectProperty class HoverBehavior(object): """ :Events: :attr:`on_enter` Call when mouse enter the bbox of the widget. :attr:`on_leave` Call when the mouse exit the widget. """ hovered = BooleanProperty(False) """ `True`, if the mouse cursor is within the borders of the widget. :attr:`hovered` is an :class:`~kivy.properties.BooleanProperty` and defaults to `False`. """ border_point = ObjectProperty(None) """Contains the last relevant point received by the Hoverable. This can be used in :attr:`on_enter` or :attr:`on_leave` in order to know where was dispatched the event. :attr:`border_point` is an :class:`~kivy.properties.ObjectProperty` and defaults to `None`. """ def __init__(self, **kwargs): self.register_event_type("on_enter") self.register_event_type("on_leave") Window.bind(mouse_pos=self.on_mouse_pos) super(HoverBehavior, self).__init__(**kwargs) def on_mouse_pos(self, *args): if not self.get_root_window(): return # do proceed if I'm not displayed <=> If have no parent pos = args[1] # Next line to_widget allow to compensate for relative layout inside = self.collide_point(*self.to_widget(*pos)) if self.hovered == inside: # We have already done what was needed return self.border_point = pos self.hovered = inside if inside: self.dispatch("on_enter") else: self.dispatch("on_leave") def on_enter(self): """Call when mouse enter the bbox of the widget.""" def on_leave(self): """Call when the mouse exit the widget.""" Factory.register("HoverBehavior", HoverBehavior)