Search code examples
pythonkivybuildozer

Save the data of the screen using Kivy library


I have been writing a script to develop an app that calculates the results of Mahjong game. I have created multiple screens to enter the players name and enter the score etc. in one of the screen I am entering the score and it is not getting saved. As soon as I move to other screen, the score data is lost. How can i save the score in the screen?

.py file looks like below

Window.size = (360, 600)

class MainScreen(Screen):
    pass

class Player_Screen(Screen):
    #pass
    #def callback(self, text):
        #self.ids.textbox.text = text

class ScreenManagement(ScreenManager):
    shared_data = StringProperty("")

Mahjong = Builder.load_file('trial_app.kv')  # Specifying location of kv file


class MainApp(App):

    def build(self):
        return Mahjong

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

my .kv file looks like below

#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import App kivy.app.App

ScreenManagement:
    #title: title # so I can use it in the .py file
    #score:score # same here

    transition: FadeTransition()
    MainScreen:
        id: title

    Player_Screen:
        id: Players
        name: 'Players'




<MainScreen>:
    name: "main"

    canvas.before:
        Color:
            rgba: 0.2, 0.5, 1, 0.5
        Rectangle:
            pos: self.pos
            size: self.size

    GridLayout:
        cols : 1

        Button:
            text: "Mahjong"
            background_normal:'Mahjong.JPG'

        Button:
            text: "Let's Play"
            on_release: app.root.current = "Contents"

<Player_Screen>:
    f_username: Name
    BoxLayout:
        orientation: 'vertical'
        id:f_username
        TextInput:
            id: Name
            hint_text:'Enter Player1'
            on_text: root.manager.shared_data = self.text #root.player_name()

        TextInput:
            id: Name
            hint_text:'Enter Player2'
            on_text: root.manager.shared_data = self.text

        TextInput:
            id: Name
            hint_text:'Enter Player3'
            on_text: root.manager.shared_data = self.text

        TextInput:
            id: Name
            hint_text:'Enter Player4'
            on_text: root.manager.shared_data = self.text

        Button:
            text: 'Back'
            on_press: self.background_color =  0,0,0,1
            on_release: root.manager.current = 'Contents'

        Button:
            text: 'Next'
            #on_press: root.callback(self.text)
            on_press: root.save_data()
            on_release: root.manager.current = 'Score'


Solution

  • First of all kindly note that your last edited code is not a reproducible one. It's sometimes quite essential to be such one.

    However if I got you right, you want to share or use the entered data in the input fields somewhere in your code as long as the application is running. If that's the requirement, you can do it in multiple ways. Here's a such one:

    To store all data centrally in shared_data make it a DictProperty.

    class ScreenManagement(ScreenManager):
        shared_data = DictProperty(rebind = True)
        # rebind is necessary for nested access in kvlang.
    

    Feed the data in the input fields using different keys as follows,

    <Player_Screen>:
        f_username: Name
        BoxLayout:
            orientation: 'vertical'
            id:f_username
            TextInput:
                id: Name
                hint_text:'Enter Player1'
                on_text: root.manager.shared_data["player1"] = self.text
    
            TextInput:
                id: Name
                hint_text:'Enter Player2'
                on_text: root.manager.shared_data["player2"] = self.text
            ...
    

    Once they are stored, you can access them anywhere from the ScreenManagement instance of your GUI (which also happens to be the root). I've added another screen to demonstrate that.

    class PlayerNameScreen(Screen):
        pass
    

    Now in kvlang for that screen,

    ...
    ScreenManagement:
        #title: title # so I can use it in the .py file
        #score:score # same here
    
        transition: FadeTransition()
        MainScreen:
            id: title
    
        Player_Screen:
            id: Players
            name: 'Players'
    
        PlayerNameScreen:
            name: "player_names"
    
    
    
    <PlayerNameScreen>:
    
        Label:
            text: "\\n".join(f"{player} : {name}" for player, name in root.manager.shared_data.items())
    
        Button:
            size_hint: None, None
            size: "100dp", "50dp"
            pos_hint: {"center_x" : 0.5, "center_y" : 0.2}
            text: "Back"
            on_release: root.manager.current = "Players"