Michael Phillips
Michael Phillips

Reputation: 33

Python - How do I add a second "screen" to my kivy application?

Note: I'm not a programmer and don't know the exact terminology I should be using. This is a basic program and I'm not trying to use literal "kivy screens" or the kivy screen manager.

I have spent hours searching all over google trying to solve this issue and I'm coming up short. I have a python kivy program. I have created the initial start screen. When the user clicks on a particular game, I want the screen to clear all data on the first screen, and then place buttons and labels on the screen. Almost like a "new" screen. I have it currently to where it clears the screen when a user selects a game, however if I try and add buttons to this screen, they populate on the main screen.

This is my python code:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.dropdown import DropDown

class MadLib(Widget):
    pass

class MadlibApp(App):
    def build(self):
        return MadLib()

app = MadlibApp()

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

Here is my .kv file:

<MadLib>:
    canvas:
        Color:
            rgba: 0.2, 0.8, 0.2, 1
        Rectangle:
            pos: 0, 0
            size: self.width, self.height


    Button:
        tag: 'exit'
        background_color: 0, 0, 0, 0
        height: 100
        width: 100
        center_x: root.width - self.width / 2
        top: root.top
        on_press: app.stop()
        Image:
            source: r"C:\Users\kraak\Desktop\Python\Python\basicexitbutton.gif"
            top: root.top
            center_x: root.width - self.width / 2
            size_hint_y: None
            height: '96dp'

    Button:
        tag: 'menu'
        background_color: 0, 0, 0, 0
        id: btn
        top: root.top - 10
        center_x: self.width / 2 + 10
        on_release: dropdown.open(self)
        size_hint_y: None
        height: '48dp'
        width: '175dp'
        Image:
            source: r"C:\Users\kraak\Desktop\Python\Python\basicmenubutton.gif"
            top: root.top + 10
            center_x: self.width / 2
            size_hint_y: None
            height: '96dp'

    Widget:
        on_parent: dropdown.dismiss()

    DropDown:

        id: dropdown
        on_select: btn.text = '{}'.format(args[1])

        Button:
            center_x: self.width / 2
            text: 'Browse'
            font_size: '32'
            background_color: 0, 0 ,0, 0
            size_hint_y: None
            height: '48dp'
            on_release: dropdown.select('A')

        Button:
            text: 'Categories'
            font_size: '32'
            background_color: 0, 0 ,0, 0
            size_hint_y: None
            height: '48dp'
            on_release: dropdown.select('B')

        Button:
            text: 'Settings'
            font_size: '32'
            background_color: 0, 0 ,0, 0
            size_hint_y: None
            height: '48dp'
            on_release: dropdown.select('C')

    Button:
        text: 'Game 1'
        font_size: '32'
        background_color: 0, 0 ,0, 0
        size_hint_y: None
        height: '48dp'
        top: root.top / 1.33
        center_x: root.width / 4
        on_press: root.clear_widgets()

    Button:
        text: 'Game 2'
        font_size: '32'
        background_color: 0, 0 ,0, 0
        size_hint_y: None
        height: '48dp'
        top: root.top / 1.66
        center_x: root.width / 4
        on_release: dropdown.select('C')

<Game1>:
    Button:
        id: tst
        text: 'Test'
        font_size: '32'
        background_color: 0, 0 ,0, 0
        size_hint_y: None
        height: '48dp'
        top: root.top
        center_x: root.width / 4

When the user clicks on game 1, I would like it to jump to the game 1 class, however it cannot because the program does not know it exists yet. I'm not sure how to go about fixing this.

Upvotes: 0

Views: 1441

Answers (1)

Edvardas Dlugauskas
Edvardas Dlugauskas

Reputation: 1489

You are talking about screens but do not seem to be using actual kivy screens. You need to have a ScreenManager and then create seperate Screen objects that you can put your widgets on.

It's literally the first result when you google "kivy screens", please do your homework next time.

Here's a quick tutorial on how to convert your existing code into something that properly uses Screens. Consider you have the following .kv code:

<First@Button>:
    text: "I'm first"

<Second@Button>:
    text: "I'm second..."

You want the first button to be on one screen and the second one on another. Firstly, make them into a Screen. Usually you just change the root widget to a screen and move all the other widgets to be in the screen. The example now looks like this:

<First@Screen>:
    name: "first_screen" # a name is like an id but only for the screen manager
    Button:
        text: "I'm first"

<Second@Screen>:
    name: "second_screen"
    Button:
        text: "I'm second..."

You now need a screen manager. In it, add all the screens you are going to use. I am going to make it the root widget. I'll also make it so that pressing the button on the first screen changes to the second screen and vice versa:

ScreenManager:
    First:
    Second:

<First@Screen>:
    name: "first_screen"
    Button:
        text: "I'm first"
        # root.manager.current is magic that gives you the current screen manager
        on_release: root.manager.current = "second_screen"

<Second@Screen>:
    name: "second_screen"
    Button:
        on_release: root.manager.current = "first_screen"
        text: "I'm second..."

That's it! You can change the transition types and other details, take a look at the docs.

To take a look at this example run this .py file:

from kivy.base import runTouchApp
from kivy.lang import Builder

runTouchApp(Builder.load_string("""
ScreenManager:
    First:
    Second:

<First@Screen>:
    name: "first_screen" # a name is like an id but only for the screen manager
    Button:
        text: "I'm first"
        # root.manager.current is magic that gives you the current screen manager
        on_release: root.manager.current = "second_screen"

<Second@Screen>:
    name: "second_screen"
    Button:
        on_release: root.manager.current = "first_screen"
        text: "I'm second..."   
            """))

Upvotes: 2

Related Questions