Scroll Kivy RecycleView-如何使用键盘输入滚动?

Scroll Kivy RecycleView-如何使用键盘输入滚动?,scroll,keyboard,android-recyclerview,kivy,Scroll,Keyboard,Android Recyclerview,Kivy,如何使用键盘滚动循环视图 我希望上/下键可以上下移动当前选择,并将其保留在视口中 对于奖励积分,我希望page up/page down键一次滚动一页 到目前为止,我有一个工作循环视图和键盘输入,但不知道如何连接它们 import subprocess from kivy.app import App from kivy.lang import Builder from kivy.uix.recycleview import RecycleView from kivy.uix.recyclev

如何使用键盘滚动循环视图

我希望上/下键可以上下移动当前选择,并将其保留在视口中

对于奖励积分,我希望page up/page down键一次滚动一页

到目前为止,我有一个工作循环视图和键盘输入,但不知道如何连接它们

import subprocess

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.video import Video
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
#from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.config import Config

Config.set('graphics', 'width', '1680')
Config.set('graphics', 'height', '1050')
#Config.set('graphics', 'fullscreen', 'auto')
from kivy.core.window import Window
Window.fullscreen = True

Builder.load_string('''
<MyVideo>:
    state: "play"
    options:  {'eos': 'loop'}
<SelectableLabel>:
    # Draw a background to indicate selection
    list_id : app.root.ids["list_id"]
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    #size: 500,500
<RV>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        padding: 20
        default_size: None, dp(150)
        default_size_hint: 1, None
        size_hint_y: None
        #size_hint_x: 1
        allow_stretch: True
        height: self.minimum_height
        #width: 500 #self.minimum_width
        orientation: 'vertical'
        multiselect: False
        touch_multiselect: False
<Mame>:
    orientation: "horizontal"
    RV:
        id: list_id
        video_id : video_id
        index: 0
    BoxLayout:
        orientation: "vertical"
        Image:
            allow_stretch: True
            keep_ratio: True
            size_hint_y: None
            size_hint_x: None
            width: self.parent.width
            height: self.parent.width/self.image_ratio
            source: "M:\MAME\marquees\%s.png"  % list_id.data[list_id.index]["game"]
        MyVideo:
            id: video_id
            allow_stretch: True
            #keep_ratio: False
            #size_hint_y: None
            #size_hint_x: None
            #width: self.parent.width
            #height: self.parent.width/self.image_ratio
            source : "V:\%s.mp4"  % list_id.data[list_id.index]["game"]
        Image:
            allow_stretch: True
            keep_ratio: True
            size_hint_y: None
            size_hint_x: None
            width: self.parent.width
            height: self.parent.width/self.image_ratio
            source : "M:\MAME\cpanel\%s.png"  % list_id.data[list_id.index]["game"]
    Image:
        source : "M:\MAME\cabinets\%s.png"  % list_id.data[list_id.index]["game"]
''')

class MyVideo(Video):
    def _do_video_load(self, *largs):
        try:
            return super(MyVideo, self)._do_video_load(largs)
        except:
            return

class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''



class SelectableLabel(RecycleDataViewBehavior, Image):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            if touch.is_double_tap:
                #self.selectable = False
                self.list_id.launch(self.index)
                return
            else:
                return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            self.list_id.index = index
            #print("selection changed to {0}".format(rv.data[index]))
        else:
            pass
            #print("selection removed for {0}".format(rv.data[index]))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(
            self._keyboard_closed, self, 'text')
        self._keyboard.bind(on_key_down=self._on_keyboard_down)
        f = open('golden.ini','r')
        lines = f.readlines()
        f.close()
        self.data = [{'source': "M:\MAME\marquees\%s.png"  % x.strip(), 'game': x.strip(), 'text': x.strip().capitalize()} for x in lines]

    def _keyboard_closed(self):
        print('My keyboard have been closed!')
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print('The key', keycode, 'have been pressed')
        print(' - text is %r' % text)
        print(' - modifiers are %r' % modifiers)

        # Keycode is composed of an integer + a string
        # If we hit escape, release the keyboard
        #if keycode[1] == 'escape':
        #    keyboard.release()
        if keycode[1] == 'up':
            if self.index > 0:
                self.index = self.index -1
        elif keycode[1] == 'down':
            if self.index < len(self.data)-1:
                self.index = self.index + 1


        # Return True to accept the key. Otherwise, it will be used by
        # the system.
        return True

    def launch(self,index):
        self.video_id.state = "stop"
        Window.minimize()
        #subprocess.Popen([r"C:\MAME\mame.exe", self.data[index].get("game")],cwd=r"C:\MAME")
        subprocess.call([r"C:\MAME\mame.exe", self.data[index].get("game")],cwd=r"C:\MAME")

        Window.fullscreen = True
        Window.restore()
        self.video_id.state = "play"

class Mame(BoxLayout):

    pass

class TestApp(App):
    def build(self):
        return Mame()

if __name__ == '__main__':
    TestApp().run()
导入子流程
从kivy.app导入应用程序
从kivy.lang导入生成器
从kivy.uix.recycleview导入recycleview
从kivy.uix.recycleview.views导入RecycleDataViewBehavior
从kivy.uix.label导入标签
从kivy.uix.image导入图像
从kivy.uix.video导入视频
从kivy.uix.boxlayout导入boxlayout
从kivy.properties导入布尔属性
从kivy.uix.recycleboxlayout导入recycleboxlayout
#从kivy.uix.recyclegridlayout导入recyclegridlayout
从kivy.uix.behaviors导入焦点行为
从kivy.uix.recycleview.layout导入LayoutSelectionBehavior
从kivy.config导入配置
Config.set('graphics'、'width'、'1680')
Config.set('graphics'、'height'、'1050')
#Config.set('图形'、'全屏'、'自动')
从kivy.core.window导入窗口
Window.fullscreen=True
Builder.load_字符串(“”)
:
状态:“播放”
选项:{'eos':'loop'}
:
#绘制背景以指示选择
列表id:app.root.ids[“列表id”]
在以下情况之前:
颜色:
rgba:(.0,0.9,1,3)如果自选,则为其他(0,0,0,1)
矩形:
pos:self.pos
大小:self.size
#尺寸:500500
:
viewclass:“SelectableLabel”
可选择的可循环利用布局:
填充:20
默认大小:无,dp(150)
默认大小提示:1,无
尺寸提示:无
#大小提示:1
允许拉伸:真
高度:自身最小高度
#宽度:500#自身最小宽度#
方向:“垂直”
多重选择:错误
触摸多选:错误
:
方向:“水平”
房车:
id:list\u id
视频标识:视频标识
索引:0
盒子布局:
方向:“垂直”
图片:
允许拉伸:真
保持比率:真
尺寸提示:无
大小提示:无
宽度:self.parent.width
高度:self.parent.width/self.image\u比率
来源:“M:\MAME\marquees\%s.png”%list\u id.data[list\u id.index][“game”]
我的视频:
id:video\u id
允许拉伸:真
#保留比率:False
#尺寸提示:无
#大小提示:无
#宽度:self.parent.width
#高度:self.parent.width/self.image\u比率
来源:“V:\%s.mp4”%list\u id.data[list\u id.index][“game”]
图片:
允许拉伸:真
保持比率:真
尺寸提示:无
大小提示:无
宽度:self.parent.width
高度:self.parent.width/self.image\u比率
来源:“M:\MAME\cpanel\%s.png”%list\u id.data[list\u id.index][“game”]
图片:
来源:“M:\MAME\cabines\%s.png”%list\u id.data[list\u id.index][“game”]
''')
课堂视频(视频):
def_do_视频_加载(自身,*largs):
尝试:
返回超级(MyVideo,self)。\u do\u video\u load(largs)
除:
返回
类SelectableRecycleBoxLayout(焦点行为、布局选择行为、,
可回收性布局):
“将选择和焦点行为添加到视图中。”
类SelectableLabel(RecycleDataViewBehavior,图像):
''将选择支持添加到标签''
索引=无
selected=布尔属性(False)
可选=布尔属性(真)
def刷新\视图\属性(自身、rv、索引、数据):
''捕获并处理视图更改''
self.index=索引
返回超级(SelectableLabel,self)。刷新\u视图\u属性(
rv、索引、数据)
def on_触控向下(自身,触控):
''在触地时添加选择''
如果是超级(SelectableLabel,self)。打开时触摸下(触摸):
返回真值
如果自碰撞点(*touch.pos)和自选择:
如果touch.is_双击:
#self.selective=False
self.list\u id.launch(self.index)
返回
其他:
返回self.parent。使用触摸键选择(self.index,touch)
def应用选项(选择了自身、rv、索引):
''响应视图中的项目选择''
self.selected=是否选中
如果选择了以下选项:
self.list\u id.index=索引
#打印(“选择更改为{0}”。格式(rv.data[index]))
其他:
通过
#打印(“删除了对{0}的选择”。格式(rv.data[index]))
RV级(回收利用审查):
定义初始(自我,**kwargs):
超级(RV,自我)。\uuuuu初始值(**kwargs)
self.\u键盘=Window.request\u键盘(
self.\u键盘\u关闭,self,“文本”)
self.\u keyboard.bind(按键盘上下=按键盘上下)
f=打开('golden.ini','r')
行=f.读行()
f、 关闭()
self.data=[{'source':“M:\MAME\marquees\%s.png”%x.strip(),'game':x.strip(),'text':x.strip().capitalize()}用于行中的x]
def_键盘_关闭(自身):
打印('我的键盘已关闭!')
self.\u keyboard.unbind(按键盘上下=self.\u键盘上下)
self.\u键盘=无
键盘上下定义(self、键盘、键码、文本、修改器):
打印('按键',按键代码'已按下')
打印('-text为%r'%text)
打印('-modifiers是%r'%modifiers)
#键码由一个整数+一个字符串组成
#如果我们点击escape,释放键盘
#如果keycode[1]=“escape”:
#键盘释放()
如果键码[1]=“向上”:
如果self.index>0:
self.index=self.index-1
elif密钥码[1]