class TreeWidget(Widget, FocusBehavior):
def __init__(self, **kwargs):
super(TreeWidget, self).__init__(**kwargs)
def on_touch_down(self, touch):
ret = super(TreeWidget, self).on_touch_down(touch)
if not self.collide_point(*touch.pos):
return ret
self.focus = True
# ...
return ret
This sets the focus to the widget for the brief moment between mouse-down and mouse-up.
Attempt 2 was to add the below code below; this doesn't help in any (visible) way; i.e. after releasing the mouse my widget still has no focus.
class ...
def on_touch_up(self, touch):
if self.collide_point(*touch.pos):
self.focus = True
ret = super(TreeWidget, self).on_touch_down(touch)
return ret
return True # (attempt 2b, also unsuccessful)
class TreeWidget(Widget, FocusBehavior):
def __init__(self, **kwargs):
super(TreeWidget, self).__init__(**kwargs)
def on_touch_down(self, touch):
ret = super(TreeWidget, self).on_touch_down(touch)
if not self.collide_point(*touch.pos):
return ret
touch.grab(self)
self.focus = True
# ...
return ret
def on_touch_up(self, touch):
# Taken from the docs: https://kivy.org/docs/guide/inputs.html#grabbing-touch-events
if touch.grab_current is self:
# ok, the current touch is dispatched for us.
# do something interesting here
print('Hello world!')
self.focus = True
# don't forget to ungrab ourself, or you might have side effects
touch.ungrab(self)
# and accept the last up
return True
Although this solution works, I don't understand why. This means I'm sure to run into a related problem very soon. Could someone explain to me what I'm doing wrong (or right). In particular, what's causing the loss of focus on mouse up (in all the solutions) and why isn't this repaired in solution 2?
Context: a desktop application on Kivy v1.9.1, Python v3.4.3.
That should work, unless other widgets do funny stuff with the grab of on_touch_up?def on_touch_down(self, touch): if self.collide_point(*touch.pos):
self.focus = True
return True
else:return super(TreeWidget, self).on_touch_down(touch)
from sys import argv
from kivy.app import App
from kivy.uix.widget import Widgetfrom kivy.uix.behaviors.focus import FocusBehavior
class Attempt(Widget, FocusBehavior): def keyboard_on_key_down(self, window, keycode, text, modifiers): result = FocusBehavior.keyboard_on_key_down(self, window, keycode, text, modifiers)
code, textual_code = keycode print("I appear to have focus", code)
return result
class Attempt1(Attempt):
def on_touch_down(self, touch): ret = super(Attempt1, self).on_touch_down(touch)
if not self.collide_point(*touch.pos): return ret
self.focus = True
return ret
class Attempt2(Attempt):
def on_touch_down(self, touch): ret = super(Attempt2, self).on_touch_down(touch)
if not self.collide_point(*touch.pos): return ret
self.focus = True
return ret
def on_touch_up(self, touch):
if self.collide_point(*touch.pos): self.focus = True
ret = super(Attempt2, self).on_touch_up(touch) return ret
class Attempt2b(Attempt):
def on_touch_down(self, touch): ret = super(Attempt2b, self).on_touch_down(touch)
if not self.collide_point(*touch.pos): return ret
self.focus = True
return ret
def on_touch_up(self, touch):
if self.collide_point(*touch.pos): self.focus = True
super(Attempt2b, self).on_touch_up(touch) return True
class Attempt3(Attempt):
def on_touch_down(self, touch): ret = super(Attempt3, self).on_touch_down(touch)
if not self.collide_point(*touch.pos): return ret
touch.grab(self)
self.focus = True
# ...
return ret
def on_touch_up(self, touch): # Taken from the docs: https://kivy.org/docs/guide/inputs.html#grabbing-touch-events if touch.grab_current is self:
self.focus = True
# don't forget to ungrab ourself, or you might have side effects touch.ungrab(self)
# and accept the last up return True
class TestApp(App):
def build(self): d = { '1': Attempt1, '2': Attempt2, '2b': Attempt2b, '3': Attempt3, } clazz = d[argv[1]] if len(argv) > 0 else Attempt1
return clazz()
def main(): TestApp().run()
if __name__ == "__main__": main()
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.behaviors import FocusBehavior
kv = '''
<FocusLabel>:
canvas.before:
Color:
rgba: [0, 1, 0, 0.25] if self.focus else [0, 0, 0, 0]
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'horizontal'
FocusLabel:
FocusLabel:
'''
class FocusLabel(FocusBehavior, Label):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
self.focus = True
return super(FocusLabel, self).on_touch_down(touch)
def keyboard_on_key_down(self, window, keycode, text, modifiers):
print("{0} got key down!".format(self))
return super(FocusLabel, self).keyboard_on_key_down(window, keycode, text, modifiers)
def on_focus(self, widget, value):
print("{0} got focus!".format(self))
return False
class TestApp(App):
def build(self):
return Builder.load_string(kv)
TestApp().run()