2

I have two screens. On Box I have a button with a name. When I click the button, I want to switch the screen to ChangeText see the name there. Once I click the button the text of Box.name should be the TextInput-text. I can't find a solution.

kv-file

<ChangeText>:
    BoxLayout:
        TextInput:
            id: txt
            multiline: False
            text: Box.name
        Button:
            text: "Save"
            on_release: Box.name = txt.text

<Box>:
    BoxLayout:
        Button:
            text: root.name
            on_press: root.change_text(root.name)

py-file

class ChangeText(Screen):
    pass

class Box(Screen):
    name = StringProperty("sometext")

    def change_text(label):
        sm.current = 'changetext'
        ### ?!?!? ###

2 Answers2

0

So I found a workaround, what might be instable but works for now. Took me hours.

I just declared eveyr property as global variable. Then I wrote a global export functio, that overwrite all global variables. So whenever I switch the screen, I execute export(props). Now all properties from my last view are exported. I need to update all properties of each screen. Therefore each screen has update(). Export() is extended by a for loop over all screens, calling the update().

home_name = ''

def export(hn):
    home_name = hn
    for screen in sm.screens:
        screen.update()

class Team(BoxLayout):
    home_name = StringProperty()

    def update(self):
        global home_name
        self.home_name = home_name 


class Box(BoxLayout):
    home_name = StringProperty("Home")

    def load_team(self):
        export(self.home_name)
        sm.current = 'team'

    def update(self):
        global home_name
        self.home_name = home_name 
        #further screen specific actions

kv

<Team>:
    id: team
    TextInput:
        id: team_name
        text: root.home_name
        multiline: False
    Button:
        text: "Save"
        on_press: root.save(team_name.text)

<Box>:
     Button:
         id: btn_home_name
         text: root.home_name
         on_press: root.load_team()
0

Problem - attribute, name

When using Kivy ScreenManager, do not declare a variable/attribute called, name because it is a reserved word used for naming/identifying a screen.

ScreenManager ยป name

name

Name of the screen which must be unique within a ScreenManager. This is the name used for ScreenManager.current.

name is a StringProperty and defaults to โ€˜โ€™.

Solution

The solution is as follow:

  1. Rename the class level property, name to home_name or anything except name
  2. Add id to each screen.
  3. Use root.manager.ids to reference widgets in declared in another screen.
  4. Replace sm.current with self.manager.current because each screen has by default a property manager that gives you the instance of the ScreenManager used.

Example

main.py

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import StringProperty


class ScreenManagement(ScreenManager):
    pass


class ChangeText(Screen):
    pass


class Box(Screen):
    home_name = StringProperty("sometext")

    def change_text(self):
        self.manager.current = 'changetext'


class TestApp(App):

    def build(self):
        return ScreenManagement()


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

test.kv

#:kivy 1.11.0

<ScreenManagement>:
    Box:
        id: box
        name: 'box'

    ChangeText:
        id: changeText
        name: 'changetext'

<ChangeText>:
    BoxLayout:
        TextInput:
            id: txt
            multiline: False
            text: root.manager.ids.box.home_name
        Button:
            text: "Save"
            on_release: root.manager.ids.box.home_name = txt.text

<Box>:
    BoxLayout:
        Button:
            text: root.home_name
            on_press: root.change_text()

Output

Img01 - Box Screen Img02 - ChangeText Screen

ikolim
  • 15,721
  • 2
  • 19
  • 29