Search code examples
pythonandroidmobilekivykivy-language

How to keep the same label text between two screens kivy


I'm new to kivy and python so my code isn't perfect. I'm trying to make a program with 2 screens, a first screen where there is a label with a text that is not defined and that can change and a second screen that keeps the same text as the first screen.

I've been searching for a week and I tried to make a global variable that I edit and that becomes the text of the second label but it doesn't work.

I also tried with String. property () or object. property () but I didn't get any more results and I didn't really understand how to use it.

Any help would be welcome <3

(sorry for my english)

Here is a part of my code that I have simplified as much as possible:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen


Builder.load_string("""

<MenuScreen>:
    label_wid : ratio
    FloatLayout:         
        Button:
            text: "options"
            pos: 270, 240
            size_hint: .30, .10
            background_color: 0,1,0,0.75
            on_press: root.manager.current = 'settings'
         Label:
            id:ratio
            text: ""
            pos: 0,90
            font_size:30
            color:1,0,0,1


<SettingsScreen>:
    label_wid2 : ratio
    FloatLayout:
        Label:
            id:ratio
            text: str(root.texte2())
            pos: 0,90
            font_size:30
            color:1,0,0,1

""")

u=""

class MenuScreen(Screen):

    def texte(self):
        global u
        u= self.label_wid.text = 'exemple' 
    pass

class SettingsScreen(Screen):

    def texte2(self):
        self.label_wid2.text=u


    pass


class Quizz(App):
    def build(self):
        self.title = 'Quizz'
        Window.clearcolor = (0, 1, 1, 0.25)
        return sm


sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))


if __name__ == '__main__':
    Quizz().run()
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen


Builder.load_string("""

<MenuScreen>:
    label_wid : ratio
    FloatLayout:         
        Button:
            text: "options"
            pos: 270, 240
            size_hint: .30, .10
            background_color: 0,1,0,0.75
            on_press: root.manager.current = 'settings'
         Label:
            id:ratio
            text: ""
            pos: 0,90
            font_size:30
            color:1,0,0,1


<SettingsScreen>:
    label_wid : ratio
    FloatLayout:
        Label:
            id:ratio
            text: root.texte2()
            pos: 0,90
            font_size:30
            color:1,0,0,1

""")

u=""

class MenuScreen(Screen):

    def texte(self):
        global u
        u= self.label_wid.text = 'exemple' 
    pass

class SettingsScreen(Screen):

    def texte2(self, text):
        u


    pass


class Quizz(App):
    def build(self):
        self.title = 'Quizz'
        Window.clearcolor = (0, 1, 1, 0.25)
        return sm


sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))


if __name__ == '__main__':
    Quizz().run() ```




Solution

  • Using a StringProperty in the ScreenManager and another in SettingsScreen provide a source of text for both Labels in the different Screens. And changing the StringProperty can change both Labels:

    from kivy.app import App
    from kivy.clock import Clock
    from kivy.properties import StringProperty
    from kivy.core.window import Window
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    
    class MenuScreen(Screen):
        pass
    
    
    class SettingsScreen(Screen):
        # this is the text to be used when the first Label text is not '1'
        theOtherText = StringProperty('Not One')
    
    
    class MyScreenManager(ScreenManager):
        # This is the text that both Labels may display
        theText = StringProperty('0')
    
    
    kv = """
    MyScreenManager:
        MenuScreen:
            name: 'menu'
        SettingsScreen:
            name: 'settings'
    
    <MenuScreen>:
        label_wid : ratio
        FloatLayout:         
            Button:
                text: "options"
                pos: 270, 240
                size_hint: .30, .10
                background_color: 0,1,0,0.75
                on_press: root.manager.current = 'settings'
            Label:
                id:ratio
                # Use theText Property from MyScreenManager
                text: root.manager.theText
                pos: 0,90
                font_size:30
                color:1,0,0,1
    
    <SettingsScreen>:
        label_wid : ratio
        FloatLayout:
            Label:
                id:ratio
                # Use theText Property from MyScreenManager
                text: '1' if root.manager.theText == '1' else root.theOtherText
                pos: 0,90
                font_size:30
                color:1,0,0,1
    
    """
    
    
    class Quizz(App):
        def build(self):
            self.title = 'Quizz'
            Window.clearcolor = (0, 1, 1, 0.25)
            Clock.schedule_once(self.change_text, 4)
            return Builder.load_string(kv)
    
        def change_text(self, dt):
            print('changing text')
            self.root.theText = '1'
    
    
    if __name__ == '__main__':
        Quizz().run()
    

    Building the MyScreenManager in the kv eliminates the need to check if the manager attribute of the Screens is set. That simplifies the logic in the kv. Then the line in kv:

    text: '1' if root.manager.theText == '1' else root.theOtherText
    

    sets the text of the second Label to 1 if the first Label text is 1, otherwise it is set to the value of theOtherText in the SettingsScreen.

    I have added a Clock.schedule_once() just for testing.