Search code examples
pythonpython-3.xuser-interfacekivykivy-language

Why is Screens not loading in Kv Language?


I have an App with three toggle buttons in a fixed header that is an outside indented layout for screen manager. On initialisation, the Import screen must show i.e. self.ids.scrn_man.current = 'import_scn" and when a toggle button is pushed a next screen should show i.e. on_state: scrn_man.current = "settings_scrn".

But for some reason, only the header is showing and the screens do not want to transition. I don't get any errors.

I tried different layouts as my Apps main class inheritance including, FloatLayout, StackLayout and BoxLayout. I also made the header fixed with AnchorLayout and use a different layout as the inline layout for ScreenManager. If I remove the ScreenManager I see my widgets, but of course, I cannot transition. I did at first try using TabbedPanel to house my different widgets but I encountered a constant RefError: weak object reference if I added too many widgets (but that's not for now). So I re-designed with something I knew worked on a previous App albeit less complex.

Here is my faulty code:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import StringProperty, ObjectProperty

Builder.load_string("""
<RoundedButton@Button>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.6,0,1) 
        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [8,]
<RoundedCancelButton@Button>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.2,.2,1) 
        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [8,]
<RoundedAcceptButton@Button>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: (.47,.47,.47,1) if self.state=='normal' else (.2,1,.6,1) 
        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [8,]

<TabbedContainer@ToggleButton>:
    background_color: (1, .5, 0, 1)
    background_normal: ''
    size_hint_y: None
    height: 50
    size_hint_x: (1 / 3)
    spacing: 30
<Tab>:
    canvas.before:
        Color:
            rgba: (.89, .89, .89, 1)
        Rectangle:
            size: self.size
            pos: self.pos
    orientation: 'lr-tb'
    BoxLayout:
        orientation: 'horizontal'
        size_hint_y: None
        height: 30
        canvas.before:
            Color:
                rgba: (1, .3, 0, 1)
            Rectangle:
                size: self.size
                pos: self.pos
        Label:
            text: 'Test'
            color: (1, 1, 1, 1)
            size_hint_x: 1
    StackLayout:
        orientation: 'lr-tb'
        Label:
            text: ''
            size_hint_x: 1
            size_hint_y: None
            height: 10
        TabbedContainer:
            id: import_tog
            text: 'Import'
            state: 'down'
            group: 'admin_navs'
            on_state: root.change_screen(self)
        TabbedContainer:
            id: calculate_tog
            text: 'Calculate'
            group: 'admin_navs'
            on_state: root.change_screen(self)
        TabbedContainer:
            id: settings_tog
            text: 'Settings'
            group: 'admin_navs'
            on_state: root.change_screen(self)
    BoxLayout:
        id: ui_content
        padding: 10
        ScreenManager: #Problem here I think
            id: scrn_man
            Screen:
                id: import_scrn
                name: 'import_scrn'
                StackLayout:
                    orientation: 'lr-tb'
                    Label:
                        text: ''
                        size_hint_x: 1
                    Label:
                        text: ''
                        size_hint_x: 0.2
                    RoundedButton:
                        text: 'Choose File'
                        size_hint_x: 0.2
                    TextInput:
                        id: get_file
                        readonly: True
                        size_hint_x: 0.5
                    Label:
                        text: ''
                        size_hint_x: 0.1
                    Label:
                        text: ''
                        size_hint_x: 0.2
                    RoundedButton:
                        text: 'Import'
                        size_hint_x: 0.2
                    Label:
                        text: ''
                        size_hint_x: 0.6
                StackLayout:
                    id: import_data_content
                    orientation: 'lr-tb'
                    size_hint_y: None
                    height: 90
            Screen:
                id: calculate_scrn
                name: 'calculate_scrn'
            Screen:
                id: settings_scrn
                name: 'settings_scrn'
                StackLayout:
                    orientation: 'lr-tb'
                    size_hint_x: 0.5
                    Label:
                        text: ''
                        size_hint_x: 0.1
                    Button:
                        text: 'Add Employee'
                        size_hint_x: 0.2
                    Label:
                        text: ''
                        size_hint_x: 0.2
                    Button:
                        text: 'CSV'
                        size_hint_x: 0.2
                    Label:
                        text: ''
                        size_hint_x: 0.3
                BoxLayout:
                    orientation: 'horizontal'
                    size_hint_x: 0.5
                    Label:
                        text: 'In Time'
                        size_hint_x: 0.7
                    TextInput:
                        size_hint_x: 0.3
                    Label:
                        text: 'Out Time'
                        size_hint_x: 0.7
                    TextInput:
                        size_hint_x: 0.3
                        """)
class TabbedContainer(ToggleButton):
    pass

class FileChoosePopup(Popup):
    load = ObjectProperty()

class RoundedButton(Button):
    pass
class RoundedCancelButton(Button):
    pass
class RoundedAcceptButton(Button):
    pass

class Tab(StackLayout):
    file_path = StringProperty("No file chosen")
    the_popup = ObjectProperty(None)
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        #load import window on initialisation
        import_window = self.ids.import_scrn
        self.ids.scrn_man.current = 'import_scrn'


    def change_screen(self, instance):
        if instance.text == 'Import':
            self.ids.scrn_man.current = 'import_scrn'
        elif instance.text == 'Calculate':
            self.ids.scrn_man.current = 'calculate_scrn'
        else:
            self.ids.scrn_man.current = 'settings_scrn'

class TestApp(App):
    def build(self):
        return Tab()

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

I expect that the import screen must show on initialisation and screens transition on toggle button state: down. Can someone please give me some advice on how to make my App act as explained above?


Solution

  • Your screens are loading correctly according to your settings. You need to review your entire kv string looking at your size_hint settings. Check each item that contains children and make sure that the total of size_hint_x for its children is less than or equal to 1.0 and the same for size_hint_y.