Michał Mazur
Michał Mazur

Reputation: 127

Function in kivy focuses wrong input

I'm having a trouble creating a mechanism moving to the next TextInput with arrows. This code works, but it doesn't put me in the right container. While i click right,left,right I should be at 2nd container, but I am at the one with id3. I figured out that the function which is supposed to change the self.focused attribute sometimes doesn't work, but I don't know why and how to fix it.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.properties import StringProperty

Builder.load_file("keyboardreader.kv")

class MyTextInput(TextInput):
    focused=StringProperty('id1')
       
    def change_focus(self, *args):
        app = App.get_running_app()
        if app.root is not None:
            # Now access the container.
            layout = app.root.ids["layout"]
            # Access the required widget and set its focus.
            print("Changefocus",self.focused)
            layout.ids[self.focused].focus = True
            
    def keyboard_on_key_down(self, window, keycode, text, modifiers):
        print(keycode, text, modifiers)
        focusedid=int(self.focused[2])
        if keycode[1]=="backspace":
            self.text=self.text[:-1]
        if keycode[1]=="right":            
            if int(self.focused[2])<5:
                focusedid+=1
                self.focused="id"+str(focusedid)
        elif keycode[1]=="left":
            if int(self.focused[2])>1:
                self.text=""
                focusedid-=1
                self.focused="id"+str(focusedid)
        self.change_focus()
        print("After changing",self.focused)
        return True

        #TextInput.keyboard_on_key_down(self, window, keycode, text, modifiers)            

class MainScreen(Widget):
    pass
    
                 
class TestingappApp(App):
    def build(self):
        return MainScreen()
    
TestingappApp().run()
<MainScreen>:
    CustomBox:
        id: layout
        size: root.size


<CustomBox@BoxLayout>:
    MyTextInput:
        id: id1
        focused: "id1"
    MyTextInput:
        id: id2
        focused: "id2"
    MyTextInput:
        id: id3
        focused: "id3"
    MyTextInput:
        id: id4
        focused: "id4"
    MyTextInput:
        id: id5
        focused: "id5"

Upvotes: 0

Views: 38

Answers (1)

John Anderson
John Anderson

Reputation: 39072

The problem is that you are creating focused as a StringProperty, which means that each instance of MyTextInput will have its own instance of focused, so that changes to one will not be known by the others. The fix is to make focused a class level variable, and have all the references in your code refer to that one class level variable. Like this:

class MyTextInput(TextInput):
    focused = 'id1'

    def change_focus(self, *args):
        app = App.get_running_app()
        if app.root is not None:
            # Now access the container.
            layout = app.root.ids["layout"]
            # Access the required widget and set its focus.
            print("Changefocus", MyTextInput.focused)
            layout.ids[MyTextInput.focused].focus = True

    def keyboard_on_key_down(self, window, keycode, text, modifiers):
        focusedid = int(MyTextInput.focused[2])
        if keycode[1] == "backspace":
            self.text = self.text[:-1]
        if keycode[1] == "right":
            if int(MyTextInput.focused[2]) < 5:
                focusedid += 1
                MyTextInput.focused = "id" + str(focusedid)
        elif keycode[1] == "left":
            if int(MyTextInput.focused[2]) > 1:
                self.text = ""
                focusedid -= 1
                MyTextInput.focused = "id" + str(focusedid)
        self.change_focus()
        print("After changing", MyTextInput.focused)
        return True

Upvotes: 2

Related Questions