Stephen DeVilbiss
Stephen DeVilbiss

Reputation: 25

Why isn't my Screen Manager accepting all of the screens from my .kv file?

I cannot figure out why the screen manager is not taking both of my screens, even when I simplify it.

Using Python 3.6.1 and kivy 1.11.1 via atom. windows machine.

Disp.py

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen

class OS(Screen):
    def __init__(s, **kwargs):
        super(OS, s).__init__(**kwargs)
        print('in OS class: ')
        print(s)
        print(s.manager)

class TS(Screen):
    def __init__(s, **kwargs):
        super(TS, s).__init__(**kwargs)
        print("In TS class: ")
        print(s)
        print(s.manager)

class SM(ScreenManager):
    def __init__(s, **kwargs):
        super(SM, s).__init__(**kwargs)
        s.add_widget(OS())
        s.add_widget(TS())
        print("in SM class: ")
        print(s)
        print(s.children)

class DispApp(App):
    def build(s):
        return SM()


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

and Disp.kv

<SM>:
    OS:
    TS:

<OS>:
    name: 'Open'

<TS>:
    name: 'Trials'

Output:

in OS class: 
<Screen name=''> 
None  
In TS class: 
<Screen name=''> 
None 
in OS class: 
<Screen name='Open'> 
None 
In TS class: 
<Screen name='Trials'> 
None 
in SM class: 
<__main__.SM object at 0x10F911F0> 
[<Screen name='Open'>]

A: Once initialized the TS and OS screens take on the names from the .kv file, but they have no manager.

B: Why does screen manager only have a single child?

C: I just want to open a file on the Open Screen (class OS) and then when it's open, have the file run on the Trials Screen (class TS). I think the project would be complete by now except I can't seem to get into a screen manager to reference the other class. (And I really should be able to implement a screen manager just for my general kivy knowledge)

Upvotes: 0

Views: 108

Answers (1)

amras
amras

Reputation: 1599

There are few concepts need to be made clear. First take the issue of accessing screens from ScreenManager class. ScreenManager will always have the current screen as it's children. To access different screens from ScreenManager class, you can use the screens property which will return the screen classes as a list and then you can enumerate through them to access any individual screen. You can also access a particular screen by it's name with get_screen(<name>) function of ScreenManager.

Second issue is accessing information of a screen (like it's name, manager etc.) from within it's class. When you are trying to access these information within the __init__ method of the screen, please remember that initialization of the screen is not finished yet. Hence you are getting blank and None responses. If you add a delay by Clock, then you will see the info will be returned properly.

Both of these issues are addressed and demonstrated in modified Disp.py file. Please run and you can understand the concepts as explained above:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock

class OS(Screen):
    def __init__(s, **kwargs):
        super(OS, s).__init__(**kwargs)
        Clock.schedule_once(lambda dt: s.info())
        
    def info(s):
        print('in OS class: ')
        print(s)
        print(s.manager)        

class TS(Screen):
    def __init__(s, **kwargs):
        super(TS, s).__init__(**kwargs)
        Clock.schedule_once(lambda dt: s.info())        

    def info(s):
        print('in OS class: ')
        print(s)
        print(s.manager)        

class SM(ScreenManager):
    def __init__(s, **kwargs):
        super(SM, s).__init__(**kwargs)
        print("From SM class: ")
        print(s.screens)
        print(s.screens[0])
        print(s.screens[1])
        print(s.get_screen('Open'))
        print(s.get_screen('Trials'))

class DispApp(App):
    def build(s):
        return SM()


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

Upvotes: 1

Related Questions