Search code examples
python-2.7kivykivy-language

Python/Kivy : Set value in TextBox by press enter key


i am using python-2.7 and kivy.I am using Tree view into dynamic add row.label to be selected with the up and down keys.I am trying that when the enter key pressed the text is copied the selected text is copied to TextBox.Can someone tell me how to done it?

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.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
from kivy.uix.treeview import TreeView, TreeViewLabel, TreeViewNode
from kivy.uix.label import Label

Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)

class User(Screen):

    def add_more(self):
        self.ids.rows.add_row()


class TreeviewGroup(Popup):
    treeview = ObjectProperty(None)
    tv = ObjectProperty(None)

    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.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':
            print(node.text)
            keyboard.release()
            self.dismiss()

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 Row(BoxLayout):
    button_text = StringProperty("")
    popup = ObjectProperty(None)

    def display_groups(self, instance):
        if len(instance.text) > 0:
            if self.popup is None:
                self.popup = TreeviewGroup()
            self.popup.open()



class Rows(BoxLayout):
    row_count = 0

    def __init__(self, **kwargs):
        super(Rows, self).__init__(**kwargs)
        self.add_row()

    def add_row(self):
        self.row_count += 1
        self.add_widget(Row(button_text=str(self.row_count)))


class Test(App):

    def build(self):
        return self.root


if __name__ == '__main__':
    Test().run()

test.kv

<Button@Button>:
    font_size: 15
    font_name: 'Verdana'


<TextInput@TextInput>:
    font_size: 15
    font_name: 'Verdana'
    padding_y: 3


<Row>:
    size_hint_y: None
    height: self.minimum_height
    height: 40

    Button:
        text: root.button_text
        size_hint_x: None
        top: 200

    TextInput:
        text: ' '
        width: 300
        multiline: False
        on_text_validate: test2.focus = True
        on_focus: root.display_groups(self)


<Rows>:
    size_hint_y: None
    height: self.minimum_height
    orientation: "vertical"

User:
    BoxLayout:
        orientation: "vertical"
        padding : 20, 5

        ScrollView:
            Rows:
                id: rows


        BoxLayout:
            orientation: "horizontal"
            size_hint_x: .2
            size_hint_y: .2

            Button:
                text: "+Add More"
                on_press: root.add_more()

<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"

        BoxLayout:
            id: treeview
        Button:
            size_hint: 1, 0.1
            text: "Close"
            on_release: root.dismiss()

Solution

  • The TreeviewGroup is used to fill a TextInput so it should have that field as an attribute and thus access that widget and set the text.

    class TreeviewGroup(Popup):
        treeview = ObjectProperty(None)
        tv = ObjectProperty(None)
    
        def __init__(self, text_input, **kwargs):
            super(TreeviewGroup, self).__init__(**kwargs)
            self.text_input = text_input # set property
            self.tv = TreeView(root_options=dict(text=""),
                           hide_root=False,
                           indent_level=4)
            ...
    
        def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
            ...
            elif key == 'enter':
                self.text_input.text = node.text # set text
                keyboard.release()
                self.dismiss()
    
    
    ...
    class Row(BoxLayout):
        button_text = StringProperty("")
        popup = ObjectProperty(None)
    
        def display_groups(self, instance, value):
            if len(instance.text) > 0 and value:
                if self.popup is None:
                    self.popup = TreeviewGroup(instance) # pass TextInput
                self.popup.open()