Search code examples
pythonkivykivy-language

Multiple classes in one screen stops FloatLayout from working correctly


I am trying to incorporate ads into a Kivy app I made, and to do this, I want to have one class (with the ads) in a FloatLayout to be at the top of my screen, and the rest of the app to be below, in a separate class.

I was trying to get this to work with some test code (simple .py and .kv file that has multiple screens and classes and organizes accordingly). The code is supposed to have two float layouts: One has text, the other has a button that you press and it takes you to the next screen. However the issue I am having is that I can't position the button correctly, as it appears that the widget is shrunk in the bottom left corner. It is supposed to be next to the text box.

Here is my .kv file:

WindowManager:
    Screen1:
    Screen2:

<Screen1>:
    name: "screen1"
    FloatLayout:
        Label:
            pos_hint: {'top': 1, "center_x": 0.5}
            size_hint: (0.2, 0.5)
            font_size: 40
            text: "TEXT AT TOP OF SCREEN"
    FloatLayout:
        TextInput:
            pos_hint: {"x": 0.1, "y": 0.05}
            size_hint: (0.3, 0.05)
            multline:False
    GoS:
        FloatLayout:
            Button:
                text: "PRESS TO GO TO SCREEN 2"
                pos_hint: {"right": 0.5, "center_y": 0.7}
                on_press: widget.goscreen()

<Screen2>:
    name: "screen2"
    Label:
        text: "YOU ARE ON SCREEN TWO"

and here is the .py file:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager, Screen

class Screen1(Screen):
    pass

class GoS(Widget):
    def goscreen(self):
        self.parent.current = "screen2"

class Screen2(Screen):
    pass

class WindowManager(ScreenManager):
    pass

kv = Builder.load_file("rec_view.kv")

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

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

Why is this happening?

Another small point also is that my button doesn't work because I can't seem to call the correct class. If I use "root.goscreen()", it doesn't work as my root widget doesn't have this function. What should be the correct syntax here?


Solution

  • I recommend you to use BoxLayout to divide your GUI.

    Your button don't work because you don't link it to a valid Widget.

    The GoS widget must be define in KV or be imported.

    Here is a proposition for your rec_view.kv file :

    WindowManager:
        Screen1:
        Screen2:
    
    <GoS>:
        Button:
            text: "PRESS TO GO TO SCREEN 2"
            on_press: root.goscreen()
    
    <Screen1>:
        name: "screen1"
        BoxLayout:
            orientation: "vertical"
            BoxLayout:
                orientation: "horizontal"
                size_hint_y: 0.5   # Proportion of screen height that the widget occupe
                Label:
                    font_size: 40
                    text: "TEXT AT TOP OF SCREEN"
            BoxLayout:
                orientation: "horizontal"
                size_hint_y: 0.3
                TextInput:
                    multline:False
            BoxLayout:
                orientation: "horizontal"
                size_hint_y: 0.2
                GoS:
    
    <Screen2>:
        name: "screen2"
        Label:
            text: "YOU ARE ON SCREEN TWO"
    

    The definition of goscreen is not correct, GoS is not a Screen, so his parent don't have current , use instead App.get_running_app().root.current = "screen2".

    I don't know what you want to do and why you define the GoS class, but you can avoid it. By moving the goscreen definition into Screen1 class, and replace the 3rd BoxLayout of Screen1 with this:

        BoxLayout:
            orientation: "horizontal"
            size_hint_y: 0.2
            Button:
                text: "PRESS TO GO TO SCREEN 2"
                on_press: root.goscreen()