Search code examples
pythonkivy

Kivy ScreenManager not showing first screen


I know this question has been asked before, but none of the solutions works for me.

I have a simple login screen:

class Login(Screen):
    def build(self):
        self.window = GridLayout()
        self.window.cols = 1
        self.window.size_hint = (0.6, 0.7)
        self.window.pos_hint = {"center_x": 0.5, "center_y": 0.5}

        self.window.add_widget(Image(
            source="logo.png",
            size_hint=(10, 10)
        ))

        self.username = Label(
            text="Username",
            font_size=50,
            bold=True
        )
        self.window.add_widget(self.username)

        self.userinp = TextInput(
            multiline=False,
            padding_y=(20, 20),
            size_hint=(1, 0.8)
        )
        self.window.add_widget(self.userinp)

        self.password = Label(
            text="Password",
            font_size=50,
            bold=True
        )
        self.window.add_widget(self.password)

        self.passwordinp = TextInput(
            multiline=False,
            size_hint=(1, 0.8)
        )
        self.window.add_widget(self.passwordinp)

        self.login = Button(
            text="Login",
            size_hint=(1, 0.8),
            bold=True
        )
        self.login.bind(on_press=self.callback)
        self.window.add_widget(self.login)

        return self.window

    def callback(self, instance):
        print("button pressed")
        username = self.userinp.text
        password = self.passwordinp.text
        try:
            with open('passwords.json') as f:
                data = json.load(f)
        except FileNotFoundError:
            print("Error")
            return {}
        if username not in data:
            print('User not found')
            return
        elif data[username] != password:
            self.login.text = ('Incorrect password')
            return
        else:
            self.login.text = ('Login successful')
            self.cusername = username,
            root.manager.current = "Home"

If I start this in isolation, changing Login's inheritance to App and using:

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

Then it all works. However, if I try to use ScreenManager and make Login my first screen, I get a blank window.

class AppManager(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(Login(name = "Login"))
        #sm.add_widget(home(name = "Home"))
        sm.current = "Login"
        return sm



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

I can see that the AppManager build is being called because I get an error on the console if I set current to anything else. It looks like the Login build isn't being executed, but I can't work out why.


Solution

  • You have defined a build() method for your Login class, however, unlike an App class, nothing is going to call your build() method. You can correct this by just calling that build() method in an __init__() method, like this:

    class Login(Screen):
        def __init__(self, **kwargs):
            super(Login, self).__init__(**kwargs)
            self.add_widget(self.build())