How To Make Tooltip Using Kivy?
I want to see tooltip as in Qt when the mouse pointer is hovering over icon in ActionBar. Yes, I can use mode='spinner', but icons are nicer.
Solution 1:
A simple example you can improve and extend:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.actionbar import ActionButton
from kivy.uix.label import Label
from kivy.clock import Clock
Builder.load_string("""
<Tooltip>:
size_hint: None, None
size: self.texture_size[0]+5, self.texture_size[1]+5
canvas.before:
Color:
rgb: 0.2, 0.2, 0.2
Rectangle:
size: self.size
pos: self.pos
<MyWidget>
ActionBar:
ActionView:
MyActionButton:
icon: 'atlas://data/images/defaulttheme/audio-volume-high'
MyActionButton:
icon: 'atlas://data/images/defaulttheme/audio-volume-high'
""")
classTooltip(Label):
passclassMyActionButton(ActionButton):
tooltip = Tooltip(text='Hello world')
def__init__(self, **kwargs):
Window.bind(mouse_pos=self.on_mouse_pos)
super(ActionButton, self).__init__(**kwargs)
defon_mouse_pos(self, *args):
ifnot self.get_root_window():
return
pos = args[1]
self.tooltip.pos = pos
Clock.unschedule(self.display_tooltip) # cancel scheduled event since I moved the cursor
self.close_tooltip() # close if it's openedif self.collide_point(*self.to_widget(*pos)):
Clock.schedule_once(self.display_tooltip, 1)
defclose_tooltip(self, *args):
Window.remove_widget(self.tooltip)
defdisplay_tooltip(self, *args):
Window.add_widget(self.tooltip)
classMyWidget(Widget):
passclassClientApp(App):
defbuild(self):
return MyWidget()
if __name__ == '__main__':
ClientApp().run()
First I bind on_mouse_pos
method to Window.mouse_pos
event so I can detect when the mouse cursor hovers over my subclass of ActionButton
. This is based on this snippet. Then I shedule an action with Clock.schedule_once()
to make my toolbox visible if I won't move my cursor. To display I'm just adding a subclass of Label to the stack of widgets. You can replace display_tooltip()
and close_tooltip()
methods with more sophisticated ones.
EDIT: Updated the code accordingly to this answer
Solution 2:
Extended Spinner with Tooltip
OK, I have extend it a little bit.
Now it's possible to set tooltip text in KV language. So every object/instance would have its own tooltip.
Tooltip
and its text tooltip_txt
, are properties of the ToolTipSpinner
.
from kivy.app import App
from kivy.core.window import Window
Window.minimum_width, Window.minimum_height = 800, 600from kivy.clock import Clock
from kivy.compat import string_types
from kivy.uix.spinner import Spinner
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.properties import ObjectProperty
from kivy.factory import Factory
from kivy.lang import Builder
Builder.load_string("""
<ToolTipSpinner>:
<Tooltip>:
size_hint: None, None
size: self.texture_size[0]+5, self.texture_size[1]+5
canvas.before:
Color:
rgb: 0.2, 0.2, 0.2
Rectangle:
size: self.size
pos: self.pos
<MyBar>:
orientation: 'horizontal'
padding: 2
spacing: 2
canvas.before:
Color:
rgba: 1, 1, 1, 1
Line:
width: 1.
rectangle: (self.x+1, self.y-1, self.width, self.height)
BoxLayout:
orientation: 'horizontal'
padding: 2,2,2,2
spacing: 2
size_hint: None, 1
width: 110
ToolTipSpinner:
id: _spinner_type_1
tooltip_txt: 'Tooltip T1'
text: 'Type 1'
values: ['0', '1', '2', '3']
size_hint: None, .45
on_text: self.on_spinner_select(self.text)
ToolTipSpinner:
id: _spinner_type_2
tooltip_txt: 'Tooltip T2\\nwith newline'
text: 'Type 2'
values: ['4', '5', '6', '7', '8', '9']
size_hint: None, .45
on_text: self.on_spinner_select(self.text)
""")
classTooltip(Label):
passclassMyBar(BoxLayout):
passclassToolTipSpinner(Spinner):
tooltip_txt = StringProperty('')
tooltip_cls = ObjectProperty(Tooltip)
def__init__(self, **kwargs):
self._tooltip = Nonesuper(ToolTipSpinner, self).__init__(**kwargs)
fbind = self.fbind
fbind('tooltip_cls', self._build_tooltip)
fbind('tooltip_txt', self._update_tooltip)
Window.bind(mouse_pos=self.on_mouse_pos)
self._build_tooltip()
def_build_tooltip(self, *largs):
if self._tooltip:
self._tooltip = None
cls = self.tooltip_cls
ifisinstance(cls, string_types):
cls = Factory.get(cls)
self._tooltip = cls()
self._update_tooltip()
def_update_tooltip(self, *largs):
txt = self.tooltip_txt
if txt:
self._tooltip.text = txt
else:
self._tooltip.text = ''defon_spinner_select(self, text):
print(text)
defon_mouse_pos(self, *args):
ifnot self.get_root_window():
return
pos = args[1]
self._tooltip.pos = pos
Clock.unschedule(self.display_tooltip) # cancel scheduled event since I moved the cursor
self.close_tooltip() # close if it's openedif self.collide_point(*self.to_widget(*pos)):
Clock.schedule_once(self.display_tooltip, 1)
defclose_tooltip(self, *args):
Window.remove_widget(self._tooltip)
defdisplay_tooltip(self, *args):
Window.add_widget(self._tooltip)
classMainApp(App):
defbuild(self):
return MyBar()
if __name__ == '__main__':
MainApp().run()
Post a Comment for "How To Make Tooltip Using Kivy?"