Taka
Taka

Reputation: 71

Textinput focus in Python-Kivy coding

A beginner of python/kivy coding. I'm trying to make a question/answer- type program.

Attached code shows a simplified example of my issue. It shows text input dialog and one button dialog alternately by remove_widget/add_widget. My issue is, at first, text input dialog has focus in text input, but next time it appears, it loses its focus, despite stating self.gridlayout.txtinput.focus = True. Any idea how I can keep its focus?

I tried adding delay time, also tried adding txtinput.focus description in AnswerChoiceScreen's on_enter, but none of them worked.

main.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput

sm = ScreenManager()
class QALayout1(BoxLayout):
    pass

class QALayout2(BoxLayout):
    pass

class AnswerChoiceScreen(Screen):

    def __init__(self, **kwargs):
        super(AnswerChoiceScreen, self).__init__(**kwargs)
        self.gridlayout = None
        self.gridlayout = QALayout2()
        self.add_widget(self.gridlayout)

    def _create_layout(self):
        if self.gridlayout is not None:
            self.remove_widget(self.gridlayout)
        self.add_widget(self.gridlayout)

    def button1_clicked(self, *args):
        if self.gridlayout is not None:
            self.remove_widget(self.gridlayout)
        self.gridlayout = QALayout2()
        self.add_widget(self.gridlayout)
        self.gridlayout.txtinput.focus = True

    def buttonOK_clicked(self, *args):
        if self.gridlayout is not None:
            self.remove_widget(self.gridlayout)
        self.gridlayout = QALayout1()
        self.add_widget(self.gridlayout)

class myApp(App):
    def build(self):  
        self.anschoi = AnswerChoiceScreen(name = 'anschoi') 
        sm.add_widget(self.anschoi)
        sm.current = 'anschoi'
        return sm

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

my.kv

<AnswerChoiceScreen>:
    BoxLayout:
        orientation: 'vertical'
        padding: 10,40,10,40 
        spacing: 40 

<QALayout1>:
    Button1:
        id: btn1
        text: 'OK'
        on_press: root.parent.button1_clicked()  


<QALayout2>:
    txtinput: txtinput
    orientation: 'vertical'
    TextInput:
        id: txtinput
        text: ''
        multiline: False
        focus: True
    ButtonOK:
        id:ButtonOK
        text: 'OK'
        on_press: root.parent.buttonOK_clicked()  

<Button0@Button>:
<Button1@Button>:
<ButtonOK@Button>:

Upvotes: 0

Views: 1225

Answers (1)

John Anderson
John Anderson

Reputation: 38937

Strange enough, all you need to do is to change

<QALayout1>:
    Button1:
        id: btn1
        text: 'OK'
        on_press: root.parent.button1_clicked()

to:

<QALayout1>:
    Button1:
        id: btn1
        text: 'OK'
        on_release: root.parent.button1_clicked()

Changing on_press to on_release. I believe it has to do with the focus of your TextInput being set on the on_touch_down (on_press) event, but then it loses focus due to the on_touch_up (on_release) event. So using the on_release avoids that problem. You can see this happen, by running your original code and pressing that OK button, but don't release it. The TextInput will have focus until you release your mouse button.

And you don't even need the line:

self.gridlayout.txtinput.focus = True

Upvotes: 1

Related Questions