2

I know how to write an app with kivy and I understand how to make a KivyMD app that has a navigation drawer. I can make the apps run individually but how do I combine the two?

I am new to coding and I am stuck here. Below are the codes for two mock-up apps for training purposes only. The first is a very simple app called "+5 Game" that allows the user to click a button to add 5 to the total which is then displayed in the GUI.

The second is a KivyMD app with a navigation drawer that contains two buttons. One to go to the home screen and one to go to the "+5 Game"

How do I link the button in the navigation draw to the +5 game? And what do I do about the imports at the top of the file?

This is the code for the +5 Game:

from kivymd.app import MDApp
from kivymd.uix.screen import Screen
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDRectangleFlatButton


class ClickToAdd(MDApp):
    def build(self):
        self.screen = Screen()
        self.num = 0

        self.display_number = MDLabel(text="0", font_style="H1", halign="center",
                                      pos_hint={'center_x': 0.5, 'center_y': 0.8})
        self.add5_BTN = MDRectangleFlatButton(text="+5", pos_hint={'center_x': 0.5, 'center_y': 0.65},
                                              on_release=self.add5_CMD)

        self.screen.add_widget(self.display_number)
        self.screen.add_widget(self.add5_BTN)

        return self.screen

    def add5_CMD(self, *args):
        self.num = self.num + 5
        self.display_number.text = str(self.num)


ClickToAdd().run()

This is the main GUI of the KivyMD app with a navigation drawer and a screen manager:

from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp

KV = '''
<ContentNavigationDrawer>:
    ScrollView:
        MDList:
            OneLineListItem:
                text: "Home"
                on_press:
                    root.nav_drawer.set_state("close")
                    root.screen_manager.current = "home"

            OneLineListItem:
                text: "Play +5 Game"
                on_press:
                    root.nav_drawer.set_state("close")
                    root.screen_manager.current = "plus5game"


Screen:
    MDToolbar:
        id: toolbar
        pos_hint: {"top": 1}
        elevation: 10
        title: "Navigation Drawer Test"
        left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]

    MDNavigationLayout:
        x: toolbar.height
        ScreenManager:
            id: screen_manager
            Screen:
                name: "home"
                MDLabel:
                    text: "Home Screen Stuff Goes Here"
                    halign: "center"

            Screen:
                name: "plus5game"
                MDLabel:
                    text: "+5 Game Goes here"
                    halign: "center"

        MDNavigationDrawer:
            id: nav_drawer

            ContentNavigationDrawer:
                screen_manager: screen_manager
                nav_drawer: nav_drawer
'''


class ContentNavigationDrawer(BoxLayout):
    screen_manager = ObjectProperty()
    nav_drawer = ObjectProperty()


class TestNavigationDrawer(MDApp):
    def build(self):
        return Builder.load_string(KV)


TestNavigationDrawer().run()
Ian Rajkumar
  • 149
  • 1
  • 8

1 Answers1

0

You cannot run one App inside another App, but you can use the guts of another App inside the first. In your case, you can redefine the the Plus5 App like this:

from kivymd.app import MDApp
from kivymd.uix.screen import Screen
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDRectangleFlatButton

class Plus5Screen(Screen):
    def __init__(self, **kwargs):
        super(Plus5Screen, self).__init__(**kwargs)
        self.num = 0

        self.display_number = MDLabel(text="0", font_style="H1", halign="center",
                                      pos_hint={'center_x': 0.5, 'center_y': 0.8})
        self.add5_BTN = MDRectangleFlatButton(text="+5", pos_hint={'center_x': 0.5, 'center_y': 0.65},
                                              on_release=self.add5_CMD)

        self.add_widget(self.display_number)
        self.add_widget(self.add5_BTN)

    def add5_CMD(self, *args):
        self.num = self.num + 5
        self.display_number.text = str(self.num)


class ClickToAdd(MDApp):
    def build(self):
        self.screen = Plus5Screen()
        return self.screen

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

and save this is a file named plus5.py.

Then in you main App, you can just reference this in the 'kv':

KV = '''
#:import Plus5Screen plus5   # import the guts of the Plus5 game
<ContentNavigationDrawer>:
    ScrollView:
        MDList:
            OneLineListItem:
                text: "Home"
                on_press:
                    root.nav_drawer.set_state("close")
                    root.screen_manager.current = "home"

            OneLineListItem:
                text: "Play +5 Game"
                on_press:
                    root.nav_drawer.set_state("close")
                    root.screen_manager.current = "plus5game"


Screen:
    MDToolbar:
        id: toolbar
        pos_hint: {"top": 1}
        elevation: 10
        title: "Navigation Drawer Test"
        left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]

    MDNavigationLayout:
        x: toolbar.height
        ScreenManager:
            id: screen_manager
            Screen:
                name: "home"
                MDLabel:
                    text: "Home Screen Stuff Goes Here"
                    halign: "center"

            Plus5Screen:  # this creates the guts of the Plu5 game
                name: "plus5game"

        MDNavigationDrawer:
            id: nav_drawer

            ContentNavigationDrawer:
                screen_manager: screen_manager
                nav_drawer: nav_drawer
'''
John Anderson
  • 35,991
  • 4
  • 13
  • 36
  • Brilliant. Another question. If I want to add another game (for example "Plus 6") to another screen, how would I add that to the build function after creating the game Plus 6 in another class? – Ian Rajkumar Jul 06 '21 at 22:20
  • You can do ir exactly the same with another game. The key is to separate the game screen and logic from the game `App` class. – John Anderson Jul 06 '21 at 23:13
  • okay but how do I add it to the build function since it already has self.screen = Plus5Screen. I am sure can't add "self.screen = Plus6Screen" after "self.screen = Plus5Screen" – Ian Rajkumar Jul 06 '21 at 23:27
  • The `self.screen = Plus5Screen` is in the `plu5.py` file, so the `self.screen = Plus6Screen` would be in the `plus6.py` file. – John Anderson Jul 07 '21 at 11:47