Search code examples
pythonoopuser-interfacekivykivy-language

How do I define what happens when user enter's text in TextInput and presses enter in Kivy?


I am trying to create a simple Chatbot application UI using Kivy and Python but I'm stuck at the very first stage. How do I access the TextInput widget inside the BoxLayout to fetch it's contents?

I read that the function on_text_validate() is called whenever you press 'Enter' on the TextInput. However this code down below doesn't seem to be functioning.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import Screen, ScreenManager, FadeTransition
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty
from kivy.lang import Builder

Builder.load_string('''
#:import AnchorLayout kivy.uix.anchorlayout
#:import Layout kivy.uix.layout
<ChatBotScreen>:
    BoxLayout:
        orientation: 'vertical'

        ScrollView:
            Label:
                size_hint_y: None
                height: self.texture_size[1]
                text_size: self.width, None
                botOutput: root.botOutput
        ScrollView:
            Label:
                size_hint_y: None
                height: self.texture_size[1]
                text_size: self.width, None
                userInput: root.userInput
        TextInput:
            id: ti_userinput
            multiline: False
''')

class ChatBotScreen(Screen):
    userInput = StringProperty()
    botOutput = StringProperty()

    def on_text_validate(self):
        text_input_userInput = self.ids['ti_userinput'].text
        self.ids['ti_userinput'].text = ''
        print(text_input_userInput)

    def UserInput(self):
        pass
    def BotOutput(self):
        pass

sm = ScreenManager(transition=FadeTransition())
sm.add_widget(ChatBotScreen(name='mainchat'))    

class MyApp(App):
    def build(self):
        return sm

Please guide me.


Solution

  • The problem in your case is that on_text_validate is not a method of the Screen class, but of TextInput, so you will never call on_text_validate of the ChatBotScreen class, what you can do is invoke that method from the on_text_validate event of the TextInput:

    Builder.load_string('''
    #:import AnchorLayout kivy.uix.anchorlayout
    #:import Layout kivy.uix.layout
    <ChatBotScreen>:
        BoxLayout:
            orientation: 'vertical'
    
            ScrollView:
                Label:
                    size_hint_y: None
                    height: self.texture_size[1]
                    text_size: self.width, None
                    botOutput: root.botOutput
            ScrollView:
                Label:
                    size_hint_y: None
                    height: self.texture_size[1]
                    text_size: self.width, None
                    userInput: root.userInput
            TextInput:
                id: ti_userinput
                multiline: False
                on_text_validate: root.on_text_validate()
    ''')
    
    class ChatBotScreen(Screen):
        userInput = StringProperty()
        botOutput = StringProperty()
    
        def on_text_validate(self):
            text_input_userInput = self.ids['ti_userinput'].text
            self.ids['ti_userinput'].text = ''
            print(text_input_userInput)
    
    sm = ScreenManager(transition=FadeTransition())
    sm.add_widget(ChatBotScreen(name='mainchat'))    
    
    class MyApp(App):
        def build(self):
            return sm