ReiAcul
ReiAcul

Reputation: 29

How to change current screen in Kivy

I'm using the screen manager in Kivy but for some reason it will not let me change my current screen using the screenManager.current method.

from kivymd.app import MDApp
from kivymd.uix.list import MDList, TwoLineListItem
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivymd.uix.button import MDFloatingActionButton, MDRectangleFlatButton
from kivymd.uix.textfield import MDTextField
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager


screen_helper = """
ScreenManager:
    LoginScreen:
        id: login_scr
    ListScreen:
        id: list_scr

<LoginScreen>:
    name: 'login'
    MDTextField:
        id: email
        hint_text: "Email"
        pos_hint: {'center_x':0.5, 'center_y':0.6}
    MDTextField:
        id: password
        hint_text: "Password"
        password: True
        pos_hint: {'center_x':0.5, 'center_y':0.5}
    MDRectangleFlatButton:
        text: 'Login'
        id: login
        pos_hint: {'center_x':0.25, 'center_y':0.4}
        on_press: app.login()
    MDRectangleFlatButton:
        id: account
        text: 'Create Account'
        pos_hint: {'center_x':0.75, 'center_y':0.4}
        on_press: app.create_account()

<ListScreen>:
    name: 'list'
    ScrollView:
        MDList:
            id: assignmentList
    MDFloatingActionButton:
        icon: 'plus'
        pos_hint: {'center_x':0.9, 'center_y':0.05}
        on_press: root.manager.current = 'assignment'
    MDFloatingActionButton:
        icon: 'theme-light-dark'
        pos_hint: {'center_x':0.1, 'center_y':0.05}
        on_press: app.show_theme_picker()
    MDRectangleFlatButton
        id: sortButton
        pos_hint: {'center_x':0.5, 'center_y':0.05}
        text: "Sorted by: Deadline"
        on_press: app.sort()
"""


class LoginScreen(Screen):
    pass


class ListScreen(Screen):
    pass


sm = ScreenManager()
sm.add_widget(LoginScreen(name='login'))
sm.add_widget(ListScreen(name='list'))


class AssignmentTracker(MDApp):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def build(self):
        self.theme_cls.theme_style = "Dark"
        screen = Builder.load_string(screen_helper)
        return screen

    def login(self):
        print(sm.current_screen)
        sm.current = 'list'

Window.size = (350, 700)
AssignmentTracker().run()

For some reason sm.current = 'list' changes the screen as can be seen by pressing the login button again because sm.current_screen outputs it as list screen but the screen displayed does not change

Upvotes: 0

Views: 403

Answers (1)

John Anderson
John Anderson

Reputation: 39117

The main problem with your code is that you are building your GUI twice. The code:

    screen = Builder.load_string(screen_helper)

builds the GUI using the kv rules in the screen_helper string. And the code:

sm = ScreenManager()
sm.add_widget(LoginScreen(name='login'))
sm.add_widget(ListScreen(name='list'))

also builds the GUI, but without the benefit of the kv rules in screen_helper (because the screen_helper has not yet been loaded).

Then, your build() method returns the result of the GUI built using Builder, and the sm is ignored. So, while sm is a ScreenManager, it is not the one that your App is actually using (it is using the screen).

So, your login() method makes a change to the sm, which is not part of your App. The fix is just to change login() to refer to the correct ScreenManager:

def login(self):
    print(self.root.current_screen)
    self.root.current = 'list'

And you can remove the lines:

sm = ScreenManager()
sm.add_widget(LoginScreen(name='login'))
sm.add_widget(ListScreen(name='list'))

Upvotes: 1

Related Questions