kivy : 如何使用 scroll 处理 _on_keyboard_down 事件
kivy :How to work _on_keyboard_down event with scroll
我在 Tree View
.label 中使用 _on_keyboard_down
事件来选择 up
和 down
keys.I 在 [=14= 中添加滚动] List.Can 有人告诉我如何在需要滚动时使用 up
和 down
滚动吗?
.py
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
h = NumericProperty(0)
popup = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
rows = [('test1'),('test2'),('test3'),('test4'),('test5'),('test6')]
tree = []
for r in rows:
tree.append({'node_id': r, 'children': []})
for branch in tree:
populate_tree_view(self.tv, None, branch)
#self.remove_widgets()
self.treeview.add_widget(self.tv)
Clock.schedule_once(self.update, 1)
self.bind(on_open=self.on_open)
def on_open(self, *args):
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down=self._on_keyboard_down)
if self.tv.selected_node is None:
self.tv.select_node(self.tv.root.nodes[0])
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
node = self.tv.selected_node
_, key = keycode
if key in ('down', 'up'):
parent = node.parent_node
ix = parent.nodes.index(node)
nx = ix+1 if 'down' else ix-1
next_node = parent.nodes[nx % len(parent.nodes)]
self.tv.select_node(next_node)
return True
elif key == 'enter':
App.get_running_app().root.name.text = node.text
keyboard.release()
self.dismiss()
def remove_widgets(self):
for child in [child for child in self.treeview.children]:
self.treeview.remove_widget(child)
def update(self, *args):
self.h = len([child for child in self.tv.children]) * 24
.kv
<TreeviewGroup>:
treeview: treeview
title: "Select"
title_size: 17
title_font: "Verdana"
size: 800, 800
auto_dismiss: False
BoxLayout
orientation: "vertical"
ScrollView:
size_hint: 1, .9
BoxLayout:
size_hint_y: None
id: treeview
height: root.h
GridLayout:
cols : 2
row_default_height: '20dp'
size_hint: .5, 0.2
pos_hint: {'x': .25, 'y': 1}
Button:
text: 'Ok'
on_release: root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
<TreeViewLabel>:
text_size: self.size
height: 30
您必须使用 scroll_to()
method and pass the node, you must also set the height of the BoxLayout
(self.treeview) to the size of the content, in this case to the TreeView
(self.tv).
因此您必须删除 .kv 中的 height: root.h
,并且在创建 TreeView
in the .py we will make the connection there, in addition to removing that update method that is not necessary and that interrupts the operation of the ScrollView
时。
我不明白为什么它的值是 24
in:
self.h = len([child for child in self.tv.children]) * 24
再合适不过了30
也就是TreeViewLabel
的高度,另外对于这类任务使用Clock
是不合适的,使用bind()
:
self.tv.bind(minimum_height=self.treeview.setter('height'))
是解决方案。
您还必须更改:
nx = ix+1 if 'down' else ix-1
到
nx = ix+1 if key == 'down' else ix-1
否则你永远爬不上
进行所有这些更改的解决方案是:
*.py
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
h = NumericProperty(0)
popup = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
rows = [('test{}').format(i) for i in range(1, 20)]#[('test1'),('test2'),('test3'),('test4'),('test5'),('test6')]
tree = [{'node_id': r, 'children': []} for r in rows]
self.tv.bind(minimum_height=self.treeview.setter('height'))
for branch in tree:
populate_tree_view(self.tv, None, branch)
#self.remove_widgets()
self.treeview.add_widget(self.tv)
self.bind(on_open=self.on_open)
def on_open(self, *args):
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down=self._on_keyboard_down)
if self.tv.selected_node is None:
self.tv.select_node(self.tv.root.nodes[0])
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
node = self.tv.selected_node
_, key = keycode
if key in ('down', 'up'):
parent = node.parent_node
ix = parent.nodes.index(node)
nx = ix+1 if key == 'down' else ix-1
next_node = parent.nodes[nx % len(parent.nodes)]
self.tv.select_node(next_node)
self.scroll.scroll_to(next_node)
return True
elif key == 'enter':
App.get_running_app().root.name.text = node.text
keyboard.release()
self.dismiss()
def remove_widgets(self):
for child in [child for child in self.treeview.children]:
self.treeview.remove_widget(child)
*.kv
<TreeviewGroup>:
treeview: treeview
title: "Select"
title_size: 17
size: 800, 800
auto_dismiss: False
scroll: scroll
BoxLayout
orientation: "vertical"
ScrollView:
id: scroll
size_hint: 1, .9
BoxLayout:
size_hint_y: None
id: treeview
GridLayout:
cols : 2
row_default_height: '20dp'
size_hint: .5, 0.2
pos_hint: {'x': .25, 'y': 1}
Button:
text: 'Ok'
on_release: root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
建议,使用适当的名称,例如BoxLayout的名称似乎表示TreeView的名称,这会造成混乱,导致其代码可读性差。
我在 Tree View
.label 中使用 _on_keyboard_down
事件来选择 up
和 down
keys.I 在 [=14= 中添加滚动] List.Can 有人告诉我如何在需要滚动时使用 up
和 down
滚动吗?
.py
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
h = NumericProperty(0)
popup = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
rows = [('test1'),('test2'),('test3'),('test4'),('test5'),('test6')]
tree = []
for r in rows:
tree.append({'node_id': r, 'children': []})
for branch in tree:
populate_tree_view(self.tv, None, branch)
#self.remove_widgets()
self.treeview.add_widget(self.tv)
Clock.schedule_once(self.update, 1)
self.bind(on_open=self.on_open)
def on_open(self, *args):
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down=self._on_keyboard_down)
if self.tv.selected_node is None:
self.tv.select_node(self.tv.root.nodes[0])
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
node = self.tv.selected_node
_, key = keycode
if key in ('down', 'up'):
parent = node.parent_node
ix = parent.nodes.index(node)
nx = ix+1 if 'down' else ix-1
next_node = parent.nodes[nx % len(parent.nodes)]
self.tv.select_node(next_node)
return True
elif key == 'enter':
App.get_running_app().root.name.text = node.text
keyboard.release()
self.dismiss()
def remove_widgets(self):
for child in [child for child in self.treeview.children]:
self.treeview.remove_widget(child)
def update(self, *args):
self.h = len([child for child in self.tv.children]) * 24
.kv
<TreeviewGroup>:
treeview: treeview
title: "Select"
title_size: 17
title_font: "Verdana"
size: 800, 800
auto_dismiss: False
BoxLayout
orientation: "vertical"
ScrollView:
size_hint: 1, .9
BoxLayout:
size_hint_y: None
id: treeview
height: root.h
GridLayout:
cols : 2
row_default_height: '20dp'
size_hint: .5, 0.2
pos_hint: {'x': .25, 'y': 1}
Button:
text: 'Ok'
on_release: root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
<TreeViewLabel>:
text_size: self.size
height: 30
您必须使用 scroll_to()
method and pass the node, you must also set the height of the BoxLayout
(self.treeview) to the size of the content, in this case to the TreeView
(self.tv).
因此您必须删除 .kv 中的 height: root.h
,并且在创建 TreeView
in the .py we will make the connection there, in addition to removing that update method that is not necessary and that interrupts the operation of the ScrollView
时。
我不明白为什么它的值是 24
in:
self.h = len([child for child in self.tv.children]) * 24
再合适不过了30
也就是TreeViewLabel
的高度,另外对于这类任务使用Clock
是不合适的,使用bind()
:
self.tv.bind(minimum_height=self.treeview.setter('height'))
是解决方案。
您还必须更改:
nx = ix+1 if 'down' else ix-1
到
nx = ix+1 if key == 'down' else ix-1
否则你永远爬不上
进行所有这些更改的解决方案是:
*.py
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
h = NumericProperty(0)
popup = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
rows = [('test{}').format(i) for i in range(1, 20)]#[('test1'),('test2'),('test3'),('test4'),('test5'),('test6')]
tree = [{'node_id': r, 'children': []} for r in rows]
self.tv.bind(minimum_height=self.treeview.setter('height'))
for branch in tree:
populate_tree_view(self.tv, None, branch)
#self.remove_widgets()
self.treeview.add_widget(self.tv)
self.bind(on_open=self.on_open)
def on_open(self, *args):
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
self._keyboard.bind(on_key_down=self._on_keyboard_down)
if self.tv.selected_node is None:
self.tv.select_node(self.tv.root.nodes[0])
def _keyboard_closed(self):
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
self._keyboard = None
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
node = self.tv.selected_node
_, key = keycode
if key in ('down', 'up'):
parent = node.parent_node
ix = parent.nodes.index(node)
nx = ix+1 if key == 'down' else ix-1
next_node = parent.nodes[nx % len(parent.nodes)]
self.tv.select_node(next_node)
self.scroll.scroll_to(next_node)
return True
elif key == 'enter':
App.get_running_app().root.name.text = node.text
keyboard.release()
self.dismiss()
def remove_widgets(self):
for child in [child for child in self.treeview.children]:
self.treeview.remove_widget(child)
*.kv
<TreeviewGroup>:
treeview: treeview
title: "Select"
title_size: 17
size: 800, 800
auto_dismiss: False
scroll: scroll
BoxLayout
orientation: "vertical"
ScrollView:
id: scroll
size_hint: 1, .9
BoxLayout:
size_hint_y: None
id: treeview
GridLayout:
cols : 2
row_default_height: '20dp'
size_hint: .5, 0.2
pos_hint: {'x': .25, 'y': 1}
Button:
text: 'Ok'
on_release: root.dismiss()
Button:
text: 'Cancel'
on_release: root.dismiss()
建议,使用适当的名称,例如BoxLayout的名称似乎表示TreeView的名称,这会造成混乱,导致其代码可读性差。