使用箭头键滚动和聚焦 [英] Scrolling and focus with arrow keys

查看:88
本文介绍了使用箭头键滚动和聚焦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置一个网格布局,可以将其放在该项目上,并且可以使用箭头键(上/下和左/右)进行导航. 这个想法是针对没有触摸或鼠标的回溯过期应用程序(即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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆