Kivy : 如何在树视图中使用 on_key_down 和 on_key_up 键盘事件?
Kivy : How to use on_key_down and on_key_up keyboard event in Tree View?
我正在使用 python-2.7
和 kivy-1.10.0
。
当我单击 name
TextInput 时,会显示树视图。
我希望使用 up
和 down
键选择标签,当按下 enter
键时,文本被复制所选文本被复制到当前的初始表单单击项目时完成
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.popup import Popup
from kivy.uix.treeview import TreeView, TreeViewLabel, TreeViewNode
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
Window.size = (500, 200)
def populate_tree_view(tree_view, parent, node):
if parent is None:
tree_node = tree_view.add_node(TreeViewLabel(text=node['node_id'],
is_open=True))
else:
tree_node = tree_view.add_node(TreeViewLabel(text=node['node_id'],
is_open=True), parent)
for child_node in node['children']:
populate_tree_view(tree_view, tree_node, child_node)
tree = []
rows = [(1, 'test1', 11), (2, 'test2', 2), (3, 'test3', 3)]
for r in rows:
tree.append({'node_id': r[1], 'children': []})
class TreeViewLabel(Label, TreeViewNode):
pass
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
#ti = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
for branch in tree:
populate_tree_view(self.tv, None, branch)
self.remove_widgets()
self.treeview.add_widget(self.tv)
def remove_widgets(self):
for child in [child for child in self.treeview.children]:
self.treeview.remove_widget(child)
def select_node(self, node):
'''Select a node in the tree.
'''
if node.no_selection:
return
if self._selected_node:
self._selected_node.is_selected = False
node.is_selected = True
self._selected_node = node
print(node)
class GroupScreen(Screen):
name = ObjectProperty(None)
popup = ObjectProperty(None)
def display_groups(self, instance):
if len(instance.text) > 0:
if self.popup is None:
self.popup = TreeviewGroup()
#self.popup.filter(instance.text)
self.popup.open()
def select_node(self, node):
'''Select a node in the tree.
'''
if node.no_selection:
return
if self._selected_node:
self._selected_node.is_selected = False
node.is_selected = True
self._selected_node = node
print(node)
class Group(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Group().run()
test.kv
#:kivy 1.10.0
<TreeViewLabel>:
on_touch_down:
app.root.name.text = self.text
app.root.popup.dismiss()
<TreeviewGroup>:
id: treeview
treeview: treeview
title: "Select"
size_hint: None, None
size: 400, 200
auto_dismiss: False
BoxLayout
orientation: "vertical"
#TextInput:
#id: ti
#size_hint_y: .1
#on_text: root.filter(self.text)
BoxLayout:
id: treeview
Button:
size_hint: 1, 0.1
text: "Close"
on_release: root.dismiss()
<CustomLabel@Label>:
text_size: self.size
valign: "middle"
padding_x: 5
<SingleLineTextInput@TextInput>:
multiline: False
<GreenButton@Button>:
background_color: 1, 1, 1, 1
size_hint_y: None
height: self.parent.height * 0.150
GroupScreen:
name: name
test:test
GridLayout:
cols: 2
padding : 30,30
spacing: 10, 10
row_default_height: '40dp'
CustomLabel:
text: 'Code'
SingleLineTextInput:
id: test
multiline: False
on_text_validate: name.focus = True
CustomLabel:
text: 'Name'
SingleLineTextInput:
id: name
text:' '
multiline: False
on_focus: root.display_groups(self)
GreenButton:
text: 'Ok'
GreenButton:
text: 'Cancel'
on_press: app.stop()
您的要求可分为 2 个任务:
- 为此我们使用
Keyboard
. 检测密钥
- 选择节点,为此我们使用
select_node()
method of TreeView
that allows us to select a specific node, selected_node
即returns当前选择的节点。 (您不应覆盖 select_node 方法,请将其从您的代码中删除。)
....
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
#ti = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
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 '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()
...
class GroupScreen(Screen):
name = ObjectProperty(None)
popup = ObjectProperty(None)
def display_groups(self, instance):
if len(instance.text) > 0:
if self.popup is None:
self.popup = TreeviewGroup()
#self.popup.filter(instance.text)
self.popup.open()
...
我正在使用 python-2.7
和 kivy-1.10.0
。
当我单击 name
TextInput 时,会显示树视图。
我希望使用 up
和 down
键选择标签,当按下 enter
键时,文本被复制所选文本被复制到当前的初始表单单击项目时完成
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.popup import Popup
from kivy.uix.treeview import TreeView, TreeViewLabel, TreeViewNode
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
Window.size = (500, 200)
def populate_tree_view(tree_view, parent, node):
if parent is None:
tree_node = tree_view.add_node(TreeViewLabel(text=node['node_id'],
is_open=True))
else:
tree_node = tree_view.add_node(TreeViewLabel(text=node['node_id'],
is_open=True), parent)
for child_node in node['children']:
populate_tree_view(tree_view, tree_node, child_node)
tree = []
rows = [(1, 'test1', 11), (2, 'test2', 2), (3, 'test3', 3)]
for r in rows:
tree.append({'node_id': r[1], 'children': []})
class TreeViewLabel(Label, TreeViewNode):
pass
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
#ti = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
for branch in tree:
populate_tree_view(self.tv, None, branch)
self.remove_widgets()
self.treeview.add_widget(self.tv)
def remove_widgets(self):
for child in [child for child in self.treeview.children]:
self.treeview.remove_widget(child)
def select_node(self, node):
'''Select a node in the tree.
'''
if node.no_selection:
return
if self._selected_node:
self._selected_node.is_selected = False
node.is_selected = True
self._selected_node = node
print(node)
class GroupScreen(Screen):
name = ObjectProperty(None)
popup = ObjectProperty(None)
def display_groups(self, instance):
if len(instance.text) > 0:
if self.popup is None:
self.popup = TreeviewGroup()
#self.popup.filter(instance.text)
self.popup.open()
def select_node(self, node):
'''Select a node in the tree.
'''
if node.no_selection:
return
if self._selected_node:
self._selected_node.is_selected = False
node.is_selected = True
self._selected_node = node
print(node)
class Group(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Group().run()
test.kv
#:kivy 1.10.0
<TreeViewLabel>:
on_touch_down:
app.root.name.text = self.text
app.root.popup.dismiss()
<TreeviewGroup>:
id: treeview
treeview: treeview
title: "Select"
size_hint: None, None
size: 400, 200
auto_dismiss: False
BoxLayout
orientation: "vertical"
#TextInput:
#id: ti
#size_hint_y: .1
#on_text: root.filter(self.text)
BoxLayout:
id: treeview
Button:
size_hint: 1, 0.1
text: "Close"
on_release: root.dismiss()
<CustomLabel@Label>:
text_size: self.size
valign: "middle"
padding_x: 5
<SingleLineTextInput@TextInput>:
multiline: False
<GreenButton@Button>:
background_color: 1, 1, 1, 1
size_hint_y: None
height: self.parent.height * 0.150
GroupScreen:
name: name
test:test
GridLayout:
cols: 2
padding : 30,30
spacing: 10, 10
row_default_height: '40dp'
CustomLabel:
text: 'Code'
SingleLineTextInput:
id: test
multiline: False
on_text_validate: name.focus = True
CustomLabel:
text: 'Name'
SingleLineTextInput:
id: name
text:' '
multiline: False
on_focus: root.display_groups(self)
GreenButton:
text: 'Ok'
GreenButton:
text: 'Cancel'
on_press: app.stop()
您的要求可分为 2 个任务:
- 为此我们使用
Keyboard
. 检测密钥
- 选择节点,为此我们使用
select_node()
method ofTreeView
that allows us to select a specific node,selected_node
即returns当前选择的节点。 (您不应覆盖 select_node 方法,请将其从您的代码中删除。)
....
class TreeviewGroup(Popup):
treeview = ObjectProperty(None)
tv = ObjectProperty(None)
#ti = ObjectProperty()
def __init__(self, **kwargs):
super(TreeviewGroup, self).__init__(**kwargs)
self.tv = TreeView(root_options=dict(text=""),
hide_root=False,
indent_level=4)
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 '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()
...
class GroupScreen(Screen):
name = ObjectProperty(None)
popup = ObjectProperty(None)
def display_groups(self, instance):
if len(instance.text) > 0:
if self.popup is None:
self.popup = TreeviewGroup()
#self.popup.filter(instance.text)
self.popup.open()
...