Philipp
Philipp

Reputation: 13

Kivy ScreenManager switching "Start" screen on a condition

I am new to kivy and wanted to start a little app project. What I want to achieve:

So far I've found a working solution, but it's not really pleasing me regarding the way it works. What I want is to create ScreenManager and Screens in the .kv file and have the .py file do the logic (which screen to load by checking if userdata exists in the store).

I've tried:

<WindowManager>:
    root.check_for_user()
    MainWindow:
    UserDataWindow:
<MainWindow>:
...

Here's my working code so far:

main.py:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.storage.jsonstore import JsonStore

class LoginWindow(Screen):
    nick = ObjectProperty(None)
    isle = ObjectProperty(None)
    hemisphere_n = ObjectProperty(None)
    hemisphere_s = ObjectProperty(None)

    def submit(self):
        store = JsonStore('store.json')
        if self.hemisphere_n.state == 'down' and self.hemisphere_s.state == 'normal':
            store.put('user', nickname=self.nick.text, island=self.isle.text, hemisphere="north")
        elif self.hemisphere_n.state == "normal" and self.hemisphere_s.state == "down":
            store.put('user', nickname=self.nick.text, island=self.isle.text, hemisphere="south")

class MainWindow(Screen):
    pass        

class WindowManager(ScreenManager):
    pass

kv = Builder.load_file("my.kv")
sm = WindowManager()
store = JsonStore('store.json')
screens = [MainWindow(name="main"), LoginWindow(name="login")]

for screen in screens:
    sm.add_widget(screen)

if store.exists('user'):
    print("exists")
    sm.current = "main"
else:
    print("not found")
    sm.current = "login"

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

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

my.kv:

#:kivy 1.11.1

<MainWindow>:
    FloatLayout:
        Label:
            text:
        Button:
            text: "Go Back"
            pos_hint: {"x": 0.45, "top": 0.5}
            size_hint: (0.1, 0.05)
            on_release:
                app.root.current = "login"

<LoginWindow>:
    nick: nickname
    isle: island
    hemisphere_n: hemisphere_n
    hemisphere_s: hemisphere_s
    FloatLayout:
        Label:
            text: "Nickname:"
            pos_hint: {"x": 0.45, "top": 0.7}
            size_hint: (0.1, 0.05)
        TextInput:
            id: nickname
            multiline: False
            pos_hint: {"x": 0.4, "top": 0.65}
            size_hint: (0.2, 0.05)

        Label:
            text: "Island Name:"
            pos_hint: {"x": 0.45, "top": 0.6}
            size_hint: (0.1, 0.05)
        TextInput:
            id: island
            multiline: False
            pos_hint: {"x": 0.4, "top": 0.55}
            size_hint: (0.2, 0.05)
        Label:
            text: "Hemisphere:"
            pos_hint: {"x": 0.45, "top": 0.5}
            size_hint: (0.1, 0.05)
        ToggleButton:
            id: hemisphere_n
            text: "North"
            group: "hemisphere"
            state: "down"
            pos_hint: {"x": 0.41, "top": 0.45}
            size_hint: (0.08, 0.05)
        ToggleButton:
            id: hemisphere_s
            text: "South"
            group: "hemisphere"
            pos_hint: {"x": 0.51, "top": 0.45}
            size_hint: (0.08, 0.05)
        Button:
            text: "Submit"
            pos_hint: {"x": 0.45, "top": 0.38}
            size_hint: (0.1, 0.05)
            on_press:
                root.submit()
            on_release:
                app.root.current = "main"

Please ignore the loose ends at some points. I wanted to get this working before going any further. It now goes to the main screen (when I add the screens to screenmanager), then checks for user data and eventually switches to login. Do you have any suggestions? Thanks in advance.

Upvotes: 1

Views: 1614

Answers (3)

John Anderson
John Anderson

Reputation: 39152

You can put your Screen choice logic pretty much anywhere you want it. Here is an example of putting it in your WindowManager class:

class WindowManager(ScreenManager):
    def select_start_screen(self):
        store = JsonStore('store.json')

        self.transition = NoTransition()
        if store.exists('user'):
            print("exists")
            self.current = "main"
        else:
            print("not found")
            self.current = "login"
        self.transition = SlideTransition()

Then you can call the select_start_screen() in your build() method:

class MainApp(App):
    def build(self):
        sm.select_start_screen()
        return sm

Upvotes: 3

Nattōsai Mitō
Nattōsai Mitō

Reputation: 918

How about adding a blank screen first in addtion to @John's answer.

sm.add_widget(Screen(name='blank'))
for screen in screens:
    sm.add_widget(screen)

Upvotes: 2

John Anderson
John Anderson

Reputation: 39152

What you are seeing is the transition animation. You can eliminate that by using NoTransition() like this:

sm.transition = NoTransition()
if store.exists('user'):
    print("exists")
    sm.current = "main"
else:
    print("not found")
    sm.current = "login"
sm.transition = SlideTransition()

Upvotes: 1

Related Questions