使用箭头键滚动和聚焦 [英] Scrolling and focus with arrow keys
问题描述
我正在尝试设置一个网格布局,可以将其放在该项目上,并且可以使用箭头键(上/下和左/右)进行导航. 这个想法是针对没有触摸或鼠标的回溯过期应用程序(即android电视或家庭媒体中心).
I'm trying have a grid layout, that I can have on item foucsed, and I can navigate using the arrow keys (up/down and left/right). the idea is for a leanback expireance application (i.e. android tv, or a home media center), with no touch or mouse.
我正在尝试为此重用FocusBehavior和CompoundSelectionBehavior 我几乎有东西了,但是我不知道如何将选择内容移到下一行,左/右保持在我用鼠标单击的第一行上,并且不会移动. /p>
I'm trying to reuse the FocusBehavior and CompoundSelectionBehavior for that I have something that is almost there, but I can't figure out how do I shift the selection to the next row, left/right keep on the first row that I've click with the mouse, and doesn't move.
from kivy.uix.behaviors.compoundselection import CompoundSelectionBehavior
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.app import App
class SelectableBoxLayout(FocusBehavior, CompoundSelectionBehavior, BoxLayout):
def keyboard_on_key_down(self, window, keycode, text, modifiers):
"""Based on FocusBehavior that provides automatic keyboard
access, key presses will be used to select children.
"""
print(keycode, text, modifiers)
print(self.orientation)
if super(SelectableBoxLayout, self).keyboard_on_key_down(
window, keycode, text, modifiers):
return True
if self.orientation == 'horizontal' and keycode[1] in ['up', 'down']:
self.clear_selection()
return self.parent.keyboard_on_key_down(window, keycode, text, modifiers)
if self.select_with_key_down(window, keycode, text, modifiers):
return True
return False
def keyboard_on_key_up(self, window, keycode):
"""Based on FocusBehavior that provides automatic keyboard
access, key release will be used to select children.
"""
if super(SelectableBoxLayout, self).keyboard_on_key_up(window, keycode):
return True
if self.orientation == 'horizontal' and keycode[1] in ['up', 'down']:
self.clear_selection()
return self.parent.keyboard_on_key_up(window, keycode)
if self.select_with_key_up(window, keycode):
return True
return False
def add_widget(self, widget):
""" Override the adding of widgets so we can bind and catch their
*on_touch_down* events. """
widget.bind(on_touch_down=self.button_touch_down,
on_touch_up=self.button_touch_up)
return super(SelectableBoxLayout, self).add_widget(widget)
def button_touch_down(self, button, touch):
""" Use collision detection to select buttons when the touch occurs
within their area. """
if button.collide_point(*touch.pos):
self.select_with_touch(button, touch)
def button_touch_up(self, button, touch):
""" Use collision detection to de-select buttons when the touch
occurs outside their area and *touch_multiselect* is not True. """
if not (button.collide_point(*touch.pos) or
self.touch_multiselect):
self.deselect_node(button)
def select_node(self, node):
node.background_color = (1, 0, 0, 1)
return super(SelectableBoxLayout, self).select_node(node)
def deselect_node(self, node):
node.background_color = (1, 1, 1, 1)
super(SelectableBoxLayout, self).deselect_node(node)
def on_selected_nodes(self, gird, nodes):
print("Selected nodes = {0}".format(nodes))
if self.orientation == 'vertical':
if nodes:
row = nodes[0]
row.clear_selection()
node_src, idx_src = row._resolve_last_node()
text = 'left'
node, idx = row.goto_node(text, node_src, idx_src)
row.select_node(node)
class TestApp(App):
def build(self):
grid = SelectableBoxLayout(orientation='vertical', touch_multiselect=False,
multiselect=False)
for i in range(0, 6):
row = SelectableBoxLayout(orientation='horizontal', touch_multiselect=False,
multiselect=False)
for j in range(0,5):
b = Button(text="Button {0}".format(j))
row.add_widget(b)
grid.add_widget(row)
row.get_focus_next().focus = True
return grid
TestApp().run()
推荐答案
花点时间进行调试,但这是一个有效的示例:
Took me a while debugging, but here's a working example:
from kivy.uix.behaviors.compoundselection import CompoundSelectionBehavior
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.app import App
class SelectableBoxLayout(FocusBehavior, CompoundSelectionBehavior, BoxLayout):
def keyboard_on_key_down(self, window, keycode, text, modifiers):
"""Based on FocusBehavior that provides automatic keyboard
access, key presses will be used to select children.
"""
print(keycode, text, modifiers)
print(self.orientation)
if super(SelectableBoxLayout, self).keyboard_on_key_down(
window, keycode, text, modifiers):
return True
if self.orientation == 'horizontal' and keycode[1] in ['up', 'down']:
self.clear_selection()
return self.parent.keyboard_on_key_down(window, keycode, text, modifiers)
if self.orientation == 'vertical' and keycode[1] in ['up', 'down']:
direction = 'focus_next' if keycode[1] == 'down' else 'focus_previous'
if self.selected_nodes:
next_row = self.selected_nodes[0]._get_focus_next(direction)
else:
next_row = self.children[-1]
self.clear_selection()
self.select_node(next_row)
if next_row:
next_row.focus = True
next = next_row.children[-1]
if next and not isinstance(next, SelectableBoxLayout):
print("moving to {0}".format(next))
next.focus = True
next_row.clear_selection()
next_row.select_node(next)
return True
if self.select_with_key_down(window, keycode, text, modifiers):
return True
return False
def keyboard_on_key_up(self, window, keycode):
"""Based on FocusBehavior that provides automatic keyboard
access, key release will be used to select children.
"""
if super(SelectableBoxLayout, self).keyboard_on_key_up(window, keycode):
return True
if self.orientation == 'horizontal' and keycode[1] in ['up', 'down']:
return self.parent.keyboard_on_key_up(window, keycode)
if self.select_with_key_up(window, keycode):
return True
return False
def add_widget(self, widget, index=0):
""" Override the adding of widgets so we can bind and catch their
*on_touch_down* events. """
widget.bind(on_touch_down=self.button_touch_down,
on_touch_up=self.button_touch_up)
return super(SelectableBoxLayout, self).add_widget(widget, index)
def button_touch_down(self, button, touch):
""" Use collision detection to select buttons when the touch occurs
within their area. """
if button.collide_point(*touch.pos):
self.select_with_touch(button, touch)
def button_touch_up(self, button, touch):
""" Use collision detection to de-select buttons when the touch
occurs outside their area and *touch_multiselect* is not True. """
if not (button.collide_point(*touch.pos) or
self.touch_multiselect):
self.deselect_node(button)
def select_node(self, node):
node.background_color = (1, 0, 0, 1)
print("select: {}".format(getattr(node, 'text', 'none')))
return super(SelectableBoxLayout, self).select_node(node)
def deselect_node(self, node):
node.background_color = (1, 1, 1, 1)
print("deselect: {}".format(getattr(node, 'text', 'none')))
super(SelectableBoxLayout, self).deselect_node(node)
def on_selected_nodes(self, grid, nodes):
pass
class TestingappApp(App):
"""Basic kivy app
Edit testingapp.kv to get started.
"""
def build(self):
grid = SelectableBoxLayout(orientation='vertical', touch_multiselect=False,
multiselect=False)
for i in range(0, 6):
row = SelectableBoxLayout(orientation='horizontal', touch_multiselect=False,
multiselect=False)
for j in range(0,5):
b = Button(text="Event A\n TT {}{}".format(i, j))
row.add_widget(b)
grid.add_widget(row)
row.get_focus_next().focus = True
return grid
这篇关于使用箭头键滚动和聚焦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!