【问题标题】:kivy :How to work _on_keyboard_down event with scrollkivy:如何使用滚动处理 _on_keyboard_down 事件
【发布时间】:2018-04-02 04:48:06
【问题描述】:

我在Tree View.label 中使用_on_keyboard_down 事件来选择updown 键。我在Tree View 列表中添加了滚动。有人可以告诉我如何使用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

【问题讨论】:

  • @eyllanesc 在到达显示列表底部时是必需的,然后滚动应该使用down 键。
  • @eyllanesc 是选择也
  • @eyllanesc root.h 设置popup的高度。我在def update中设置值

标签: python-2.7 kivy kivy-language


【解决方案1】:

您必须使用scroll_to() 方法并传递节点,您还必须将BoxLayout(self.treeview) 的高度设置为内容的大小,在本例中为TreeView(self .tv)。

因此,您必须删除 .kv 中的 height: root.h,当您在 .py 中创建 TreeView 时,我们将在那里建立连接,除了删除不必要的更新方法并中断ScrollView 的操作。 我不明白为什么它的值是24 in:

self.h = len([child for child in self.tv.children]) * 24

30TreeViewLabel的高度再合适不过了,除了使用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 的名称,这会导致混淆,使其代码可读性降低。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多