Search code examples
pythonkivykivy-languagekivymd

KivyMD, Kivy, ScreenManager, TextField do not change the text


When I try to grab the Text value from my TextField, I always get empty. At the same time, if I set the default text value, for example "123", then regardless of whether I enter anything into my TextField into the console, I still get "123". I had a guess that it might be due to some kind of screen duplication, but when I call self.root.get_screen ('registration'). Ids, I get three different ids, i.e. there is no duplication. I will be glad for your help <3

my.kv

<RegistrationScreen>:
    name: "registration"
    MDCard:
        size_hint: None, None
        size: 400, 600
        orientation: "vertical"
        pos_hint: {"center_x": 0.5, "center_y": 0.5}

        padding: 15
        spacing: 50

        MDLabel:
            text: "Регистрация"
            font_name: 'fonts/montserrat-bold.ttf'
            font_size: 20

            color: .43, 0, .48, 1
            halign: "center"

        BoxLayout:
            size_hint: None, None
            size: 200, 160
            pos_hint: {"center_x": 0.5}
            orientation: "vertical"

            MDTextField:
                id: pomogite

                hint_text: "Rectangle mode"
                mode: "rectangle"
                helper_text_mode: "on_focus"

                hint_text: "Введите логин"
                helper_text: "Минимум 6 символов (a-z, A-Z, 0-9)"
                icon_right: "account"

                color_mode: 'custom'
                line_color_focus: .43, 0, .48, 1

                size_hint_x: None
                width: 250

                pos_hint: {"center_x": .5, "center_y": .3}
                text: "Начинайте ввод"

            MDTextField:
                id: textfield_password

                hint_text: "Rectangle mode"
                mode: "rectangle"
                helper_text_mode: "on_focus"

                hint_text: "Введите пароль"
                helper_text: "Минимум 6 символов (a-z, A-Z, 0-9)"
                icon_right: "form-textbox-password"

                color_mode: 'custom'
                line_color_focus: .43, 0, .48, 1

                size_hint_x: None
                width: 250

                pos_hint: {"center_x": .5, "center_y": .3}

        MDRectangleFlatButton:
            id: reg
            text: "Регистрация"
            theme_text_color: "Custom"
            text_color: .43, 0, .48, 1
            line_color: .43, 0, .48, 1
            pos_hint: {"center_x": .5}
            on_press: app.registration()

main.py

from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.app import MDApp
from client import Client
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.textfield import MDTextField


sm = ScreenManager()


class LoadingScreen(Screen):
    pass


class AuthorizationScreen(Screen):
    pass


class RegistrationScreen(Screen):
    pass



class MyApp(MDApp):

    def build(self):

        sm.add_widget(LoadingScreen(name='loading'))
        sm.add_widget(AuthorizationScreen(name='authorization'))
        sm.add_widget(RegistrationScreen(name='registration'))
        sm.switch_to(AuthorizationScreen())

        return sm

    def fff(self):
        self.screen.ids.text_field_error.error = True
        sm.switch_to(LoadingScreen())

    def registration(self):
        addwindow_instance = self.root.get_screen('registration')

        print(addwindow_instance.ids)
        print(addwindow_instance.ids["pomogite"].text)



MyApp().run()

Solution

  • A couple errors in your code, Whenever you use a classname followed by (), you are creating a new instance of that class. So the line:

    sm.switch_to(AuthorizationScreen())
    

    creates a new instance of AuthorizationScreen, in addition to the one already created by the line:

    sm.add_widget(AuthorizationScreen(name='authorization'))
    

    A better approach is to use sm.current = rather than sm.switch_to, like this:

    def build(self):
        sm.add_widget(LoadingScreen(name='loading'))
        sm.add_widget(AuthorizationScreen(name='authorization'))
        sm.add_widget(RegistrationScreen(name='registration'))
        sm.current = 'authorization'
        return sm
    

    This switched the current screen to the already existing AuthorizationScreen instance. Or, even simpler, just place the AuthorizationScreen as the first added Screen and it will become the current Screen:

    def build(self):
        sm.add_widget(AuthorizationScreen(name='authorization'))
        sm.add_widget(LoadingScreen(name='loading'))
        sm.add_widget(RegistrationScreen(name='registration'))
        return sm
    

    The same error appears in your fff() method in the line:

    sm.switch_to(LoadingScreen())
    

    which is creating a new instance of LoadingScreen rather than using the already existing one. That line should probably be:

    sm.current = 'loading'