Nirdesh Kumawat
Nirdesh Kumawat

Reputation: 406

Python/Kivy : Focus one TextInput to another TextInput using enter key

  1. How to move focus from name TextInput to first column (id:test1) of dynamic add row using press enter key?
  2. When press enter in second column (id:test2) of dynamic row then new row add . How to focus first column of every row when add new row dynamic?

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

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

class User(Screen):

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


class Row(BoxLayout):
    button_text = StringProperty("")


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:
        id:test1
        text: ' '
        width: 300
        multiline: False
        on_text_validate: test2.focus = True

    TextInput:
        id:test2
        text: ' '
        width: 300
        multiline: False
        on_text_validate: app.root.add_more()

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

User:
    BoxLayout:
        orientation: "vertical"
        GridLayout:
            cols: 2
            padding: 20, 20
            spacing: 10, 10

            Label:
                text: "Name"
                text_size: self.size
                valign: 'middle'
            TextInput:
                id:name
                multiline: False
                text_size: self.size

        ScrollView:
            Rows:
                id: rows

Upvotes: 0

Views: 2217

Answers (1)

ikolim
ikolim

Reputation: 16041

I have added the following:

  1. Clock.schedule_once to ensure that the ids are defined and set focus on name (TextInput).
  2. ObjectProperty because

it is generally regarded as ‘best practice’ to use the ObjectProperty. This creates a direct reference, provides faster access and is more explicit.

Programming Guide » Kv language » Referencing Widgets

Example

main.py

from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ObjectProperty
from kivy.clock import Clock

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


class User(Screen):
    name = ObjectProperty(None)
    rows = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(User, self).__init__(**kwargs)
        Clock.schedule_once(self.set_name_focus, 1)

    def set_name_focus(self, *args):
        self.name.focus = True

    def on_enter_text_input(self):
        self.rows.row.test1.focus = True

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


class Row(BoxLayout):
    button_text = StringProperty("")


class Rows(BoxLayout):
    row_count = 0
    row = ObjectProperty(None)

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

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


class Test(App):

    def build(self):
        return self.root


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

test.kv

#:kivy 1.10.0

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


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


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

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

    TextInput:
        id:test1
        focus: True
        text: ' '
        width: 300
        multiline: False
        on_text_validate: test2.focus = True

    TextInput:
        id:test2
        text: ' '
        width: 300
        multiline: False
        on_text_validate: app.root.add_more()

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

User:
    name: name
    rows: rows
    BoxLayout:
        orientation: "vertical"
        GridLayout:
            cols: 2
            padding: 20, 20
            spacing: 10, 10

            Label:
                text: "Name"
                text_size: self.size
                valign: 'middle'
            TextInput:
                id:name
                multiline: False
                text_size: self.size
                on_text_validate: root.on_enter_text_input()

        ScrollView:
            Rows:
                id: rows

Output

Img01 - App Startup Img02 - test1-TextInput @ Row 1 Img03 - test2-TextInput @ Row 1 Img04 - test1-TextInput @ Row 2

Upvotes: 1

Related Questions