Why does my Kivy BoxLayout not work at the top of my code but it does at the bottom?

Tyler Channer

I was in the process of moving all the initialisation python code to the main.py file that i have and in the process of doing so, my login page went from looking like this, to this. The top bar was a box layout which is not working. I wanted to check whether it was the .kv file or the python that i wrote, so I changed the position of the BoxLayout and put it at the bottom and it worked. See here. I want to know what went wrong with the code and how i can go about fixing it because this has never happened to me before.

Here is the main.py file

from kivy.app import App
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen, ScreenManager
from LogInWindow import LogInWindow  # importing the class from Login.py


class WindowManager(ScreenManager):
    pass


sm = WindowManager()

screens = [LogInWindow(name="Login_window")]
for screen in screens:
    sm.add_widget(screen)

sm.current = "Login_window"


class FitnessApp(App):
    def build(self):
        App.title = "Fitness App"
        Window.size = (1080, 720)
        return sm


if __name__ == '__main__':  # The value of __name__ attribute is set to “__main__” when module is run as main program
    FitnessApp = FitnessApp()
    FitnessApp.run()

And here is the kivy file (with the box layout on top where is does not work)

<LogInWindow>:
    id: Login_window  ## setting the id to Login_window
    orientation: "vertical"  ## setting orientation to vertical
    space_x: self.size[0]/4.5  ## setting space to a 1/4.5 of the screen either side

    BoxLayout:  ## setting up a box layout for the top bar
        size_hint_y: None  ## setting size hint to none so it can be set to anything
        height: 100  ## setting height to 100
        canvas.before:
            Color:
                rgba: (0, 0, 0, 1)  ## changing the colour of the top bar
            Rectangle:
                size: self.size  ## setting position of rect to the position of the box
                pos: self.pos  ## setting size of rect to the size of the box
        Label:  ## creating the "title"
            text: "Login"  ## setting the text
            font_size: 48  ## changing the font size
            bold: True  ## changing it to bold
            size_hint_x: .9  ## setting hint to 90%


    BoxLayout:  ## setting up a box layout for the rest of the page
        orientation: 'vertical'  ## setting orientation to vertical
        padding: Login_window.space_x, 10  ## setting the padding between box and children
        spacing: 20  ## adding a spacing between the child widgets
        canvas.before:
            Color:
                rgba: (212/255,212/255,212/255, 1)  ## setting colour to light grey
            Rectangle:
                size: self.size  ## setting size to the size of the box layout
                pos: self.pos  ## setting position to the position of the box layout
        BoxLayout:
            orientation: "vertical"  ## setting orientation to vertical
            spacing: 30  ## adding a spacing between the child widgets
            size_hint_y: None  ## setting size hint to none so it can be set to anything
            height: 170  ## setting height to 170
            canvas.before:
                Color:
                    rgba: (212/255,212/255,212/255, 1)  ## setting colour to light grey
                Rectangle:
                    size: self.size  ## setting size to the size of the box layout
                    pos: self.pos  ## setting position to the position of the box layout
            Label:
                id: info  ## setting id to info
                text: ''  ## setting the text to empty
                markup: True  ## allows styling of text
                size_hint_y: None  ## setting size hint to none so it can be set to anything
                height: 20 ## setting height to 20
            TextInput:  ## creating a text input for username
                id: username_field  ## setting the id to username_field
                size_hint_x: 1  ## setting the size hint to 1 so it spans the whole box
                hint_text: "Username"  ## setting the translucent text to username
                font_size: 24  ## setting font size to 24
                multiline: False  ## not allowing multiline inputs
                write_tab: False  ## making tab go to the password field, not create 4 spaces
                focus: True  ## lets the tab key work
                on_text_validate: password_field.focus = True  ## will check if password is filled if enter key pressed
            TextInput:  ## creating a text input for password
                id: password_field  ## setting the id to password_field
                hint_text: "Password"  ## setting the translucent text to Password
                font_size: 24  ## setting font size to 24
                multiline: False  ## not allowing multiline inputs
                write_tab: False  ## does not allow the tab to create 4 spaces
                password: True  ## sets characters to *
                on_text_validate: root.validate_user()  ## runs the function to validate
        Label:  ## creating a label for spacing
            id: spacing  ## set the id to spacing
            size_hint_y: None  ## setting size hint to none so it can be set to anything
            height: 40  ## setting height to 40
        Button:
            text: "Don't have an account? Sign Up Here!"  ## setting the text to the sign up
            font_size:20  ## changing font size
            size_hint_y: None  ## setting size hint to none so it can be set to anything
            height: 60  ## setting height to 60
            background_color: (0, 0, 0, 1)  ## setting background colour
            background_normal: ''  ## changing the background_normal to nothing
            on_release: root.validate_user()  ##will change to put it to sign up screen
        Button:
            text: "Sign In" ## setting the text to the sign in
            bold: True  ## changing it to bold
            font_size:48  ## changing font size
            size_hint_y: None  ## setting size hint to none so it can be set to anything
            height: 100  ## setting height to 100
            background_color: (0, 0, 0, 1)  ## setting background color to white
            background_normal: ''  ## background normal to nothing
            on_release: root.validate_user()  ## setting the button to validate the user
        Label:  ## creating a label for spacing
            id: spacing2   ## setting id to spacing2

And just for reference, here is the first few lines of the class that main.py opens when it is started.

class LogInWindow(Screen, BoxLayout):  # creating LogInWindow class
    kv = Builder.load_file("LogInWindow.kv")  # loading the kivy file which has all the

Any help would be greatly appreciated.

John Anderson

Your LoginWindow is using multiple inheritance of both Screen and BoxLayout. The Screen class extends RelativeLayout and therefore has a do_layout() method that follows its own rules for laying out its children. The BoxLayout also has a do_layout() that follows the BoxLayout rules for laying out its children. So, how do the children of your LoginWindow get laid out?

Python has a Method Resolution Order that determines which do_layout() method is called in this situation. In your case the do_layout() of the Screen class will be called. So, the result is that the children of LoginWindow are not laid out using BoxLayout rules, but rather using RelativeLayout rules. Which means that the last child is likely to be drawn over previous children (as you are seeing).

You must carefully consider this whenever you use multiple inheritance to avoid this common problem. I would suggest changing LoginWindow to only inherit from Screen, and just use a top level BoxLayout in its kv rule.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related