如何使用键盘滚动RecycleView?
我想使用向上/向下键来上下移动当前选择并将其保留在视口中。
对于奖励积分,我希望页面向上/向下翻页键一次滚动页面。
到目前为止,我有一个有效的循环视图和键盘输入,但无法确定如何连接它们。
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()