使用箭头键滚动和聚焦

时间:2017-11-09 21:49:02

标签: python kivy leanback

我正在尝试使用网格布局,我可以对项目进行处理,我可以使用箭头键(向上/向下和向左/向右)进行导航。 这个想法是针对瘦身后期应用程序(即android电视或家庭媒体中心),没有触摸或鼠标。

我试图重复使用FocusBehavior和CompoundSelectionBehavior 我有一些东西几乎就在那里,但我无法弄清楚如何将选择移到下一行,左/右保持在我用鼠标点击的第一行,并且没有&# 39; 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()

1 个答案:

答案 0 :(得分:0)

我花了一段时间调试,但这是一个有效的例子:

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