Good evening,
I'm trying to combine kivy's actionbar with a screenmanager. I've gotten to the point where I can switch through screens, but am not able to get my actionbar to show. I've followed alot of examples, but none that can help me with my problem. I'm fairly new to kivy so I haven't been working with it for very long.
I was kind of wondering if someone would be able to point out where my problem lies, because I'm trying to build my very own GUI with an action bar that lets me switch through screens.
here is my main.py:
#!/usr/bin/env python3
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
class Menu(BoxLayout):
pass
class ScreenThermo(Screen):
pass
class ScreenLight(Screen):
pass
class ScreenEnergy(Screen):
pass
class ScreenWeather(Screen):
pass
class Manager(ScreenManager):
screen_thermo = ObjectProperty(None)
screen_light = ObjectProperty(None)
screen_energy = ObjectProperty(None)
screen_weather = ObjectProperty(None)
class MenuApp(App):
def thermostaat(self):
print("Thermostaat")
def verlichting(self):
print("Verlichting")
def energie(self):
print("Energie")
def weer(self):
print("Het Weer")
def build(self):
return Manager()
if __name__ == '__main__':
MenuApp().run()
And here's my menu.kv file:
#:kivy 1.0.9
<Menu>:
orientation: "vertical"
ActionBar:
ActionView:
ActionPrevious:
ActionButton:
text: "Thermostaat"
on_release: app.thermostaat()
ActionButton:
text: "Verlichting"
#I want my screens to switch when clicking on this actionbar button
on_press: root.manager.current= 'light'
on_release: app.verlichting()
ActionButton:
text: "Energieverbruik"
on_release: app.energie()
ActionButton:
text: "Het Weer"
on_release: app.weer()
Button:
text: "Nothing"
background_color: 1, 1, 1, 0.6
background_normal: ""
<ScreenThermo>:
Button:
text: "stuff1"
#this is a test to see if i can switch through screens
on_press: root.manager.current= 'light'
<ScreenLight>:
Button:
text: "stuff2"
<ScreenEnergy>:
Button:
text: "stuff3"
<ScreenWeather>:
Button:
text: "stuff4"
<Manager>:
id: screen_manager
screen_thermo: screen_thermo
screen_light: screen_light
screen_energy: screen_energy
screen_weather: screen_weather
ScreenThermo:
id: screen_thermo
name: 'thermo'
manager: screen_manager
ScreenLight:
id: screen_light
name: 'light'
manager: screen_manager
ScreenEnergy:
id: screen_energy
name: 'energy'
manager: screen_manager
ScreenWeather:
id: screen_weather
name: 'weather'
manager: screen_manager
As you can see, I'm trying to have my screens switch on a actionbar button click, but somehow when i launch it, my actionbar is gone.
If anyone could help me with this issue, that would be amazing.
In the following example we will replace the root widget, Manager with Menu, the detail solution is as follow:
main.py - Python Script
1. build method
Make the class Menu the root widget by replacing:
def build(self):
return Manager()
with:
def build(self):
return Menu()
2. Menu classs
Declare a variable, manager of type ObjectProperty which we will hook it up to the ScreenManager.
class Menu(BoxLayout):
manager = ObjectProperty(None)
menu.kv - kv File
3. Hook up the ObjectProperty to id
Here we hook up the ObjectProperty, manager to the ScreenManager's id, screen_manager so that we can reference it e.g. root.manager.current.
<Menu>:
manager: screen_manager
4. Define the height of ActionBar
We set the height of the ActionBar to 10% (0.1) of the parent's height using size_hint_y = 0.1
ActionBar:
size_hint_y: 0.1
ActionView:
5. Define the height of the Button
We set the height of the Button to 10% (0.1) of the parent's height using
size_hint_y = 0.1
Button:
size_hint_y: 0.1
text: "Nothing"
6. Add ScreenManager as children of Menu
We add Manager as children of Menu after Button. Since we did not specify the height, it defaults to the remaining available height i.e. 0.8 (80% of parent's height).
Manager:
id: screen_manager
Example
main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
class Menu(BoxLayout):
manager = ObjectProperty(None)
class ScreenThermo(Screen):
pass
class ScreenLight(Screen):
pass
class ScreenEnergy(Screen):
pass
class ScreenWeather(Screen):
pass
class Manager(ScreenManager):
screen_thermo = ObjectProperty(None)
screen_light = ObjectProperty(None)
screen_energy = ObjectProperty(None)
screen_weather = ObjectProperty(None)
class MenuApp(App):
def thermostaat(self):
print("Thermostaat")
def verlichting(self):
print("Verlichting")
def energie(self):
print("Energie")
def weer(self):
print("Het Weer")
def build(self):
return Menu()
if __name__ == '__main__':
MenuApp().run()
menu.kv
#:kivy 1.10.0
<Menu>:
manager: screen_manager
orientation: "vertical"
ActionBar:
size_hint_y: 0.1
ActionView:
ActionPrevious:
ActionButton:
text: "Thermostaat"
on_release: app.thermostaat()
ActionButton:
text: "Verlichting"
#I want my screens to switch when clicking on this actionbar button
on_press: root.manager.current= 'light'
on_release: app.verlichting()
ActionButton:
text: "Energieverbruik"
on_release: app.energie()
ActionButton:
text: "Het Weer"
on_release: app.weer()
Button:
size_hint_y: 0.1
text: "Nothing"
background_color: 1, 1, 1, 0.6
background_normal: ""
Manager:
id: screen_manager
<ScreenThermo>:
Button:
text: "stuff1"
#this is a test to see if i can switch through screens
on_press: root.manager.current= 'light'
<ScreenLight>:
Button:
text: "stuff2"
<ScreenEnergy>:
Button:
text: "stuff3"
<ScreenWeather>:
Button:
text: "stuff4"
<Manager>:
id: screen_manager
screen_thermo: screen_thermo
screen_light: screen_light
screen_energy: screen_energy
screen_weather: screen_weather
ScreenThermo:
id: screen_thermo
name: 'thermo'
manager: screen_manager
ScreenLight:
id: screen_light
name: 'light'
manager: screen_manager
ScreenEnergy:
id: screen_energy
name: 'energy'
manager: screen_manager
ScreenWeather:
id: screen_weather
name: 'weather'
manager: screen_manager
Output
you never add the menu to your app also you need to add a manager property in your menu. Try something like this:
in the .py:
...
class Menu(BoxLayout):
manager = ObjectProperty(None)
...
class MenuApp(App):
def thermostaat(self):
print("Thermostaat")
def verlichting(self):
print("Verlichting")
def energie(self):
print("Energie")
def weer(self):
print("Het Weer")
...
Notice that I have removed the build method
In your kv add this block of code at the end:
...
BoxLayout: #use a box layout or whatever you want
orientation: 'vertical'
Menu:
size_hint_y: .1
manager: manager
Manager:
size_hint_y: .9
id: manager
Related
I have tried to minimize the example as much as possible but it seems empty and the problem is not exactly the same after.
I think i misunderstand things about class variables and instance variables, but Kivy doesn't help me on this : we create a lot of class but never instantiate them !
Of course I want the "Screenx instance has overwritten question" message appears and I just see "Not overwritten".
calendrier.py
from kivy.properties import StringProperty
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
class Menu(Screen):
pass
class CalculGenerique(Screen):
question = StringProperty()
def __init__(self, **kwargs):
super(CalculGenerique, self).__init__(**kwargs)
Clock.schedule_once(self.late_init, 0)
def late_init(self, *largs):
self.renew_question()
def renew_question(self):
self.question = "Not overwritten"
class Screen1(CalculGenerique):
def renew_question(self):
self.question = "Screen1 instance has overwritten question"
class Screen2(CalculGenerique):
def renew_question(self):
self.question = "Screen2 instance has overwritten question"
class MyScreenManager(ScreenManager):
pass
class CalendarApp(App):
def build(self):
root_widget = Builder.load_file("calendrier.kv")
return root_widget
if __name__ == "__main__":
app = CalendarApp()
app.run()
calendrier.kv
#:import App kivy.app.App
MyScreenManager:
Menu:
CalculGenerique:
name: 'Screen1'
CalculGenerique:
name: 'Screen2'
<Menu>:
name: 'Menu'
BoxLayout:
orientation: 'vertical'
Button:
text: 'Screen1'
on_press : app.root.current = 'Screen1'
Button:
text: 'Screen2'
on_press : app.root.current = 'Screen2'
Button:
text: 'Quitter l app'
on_press : App.get_running_app().stop()
<CalculGenerique#Screen>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Back to Menu'
on_press : app.root.current = 'Menu'
Label:
text: root.question
Your 'kv' rule:
MyScreenManager:
Menu:
CalculGenerique:
name: 'Screen1'
CalculGenerique:
name: 'Screen2'
creates two instances of the CalculGenerique class, but no instances of Screen1 or Screen2. I think you just need to change that rule to:
MyScreenManager:
Menu:
Screen1:
name: 'Screen1'
Screen2:
name: 'Screen2'
The name property of a Screen is just used to identify the Screen, and does not specify the class.
this is a trial code that I want to implement in my final project.
Python Code:
import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
class Wid(BoxLayout):
def settxt(self,i):
lab = self.ids['lab']
but = self.ids['but']
lab.text = "Label Number {}".format(i)
but.text = "Button Number {}".format(i)
class Win1(Screen):
i=0
def addw(self):
box1 = self.ids['box1']
self.i = self.i +1
w = Wid()
w.settxt(self.i)
box1.add_widget(w)
def switch(self):
sm.current="win2"
class Win2(Screen):
def switch(self):
sm.current="win1"
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("test.kv")
sm = WindowManager()
screens = [Win1(name="win1"), Win2(name="win2")]
for screen in screens:
sm.add_widget(screen)
sm.current = "win1"
class Test(App):
def build(self):
return sm
if __name__ == '__main__':
Test().run()
Kivy Code:
<Wid>:
lab:lab
but:but
BoxLayout:
height: self.minimum_height
size: root.size
Label:
id: lab
Button:
id: but
<Win1>
name:"win1"
box1:box1
BoxLayout:
height: self.minimum_height
orientation: "vertical"
BoxLayout:
size_hint: 1,0.2
Button:
text:"window 2"
on_release:
root.switch()
Button:
text:"add wid"
on_release:
root.addw()
ScrollView:
GridLayout:
id:box1
orientation: "vertical"
spacing: 2
size_hint_y: None
height: self.minimum_height
row_default_height: 60
cols:1
<Win2>
name: "win2"
BoxLayout:
id: bl
height: bl.minimum_height
size_hint_y: None
Button:
text:"window 2"
on_release:
root.switch()
With the press of the switch, I expect that my custom widget to get in the gridlayout in the scrollview, one below the other. But instead, each new widget appears in the last cell of the layout and overlaps on the previous one and empty cells keep on forming above them.
Don't know where it's going wrong.
Here I have moved the kv to a separate file, and dynamically created the screens.
Key points: I add the screens dynamically in on_start, this is after the build has completed. I create the ScreenManager in kv, and use the id to add the screens. In the kv code I put the ScreenManger in a BoxLayout. This is a personal preference. I do this so when accessing objects the root widget is not the screen manager. Therefore in the switch() methods, the addressing uses the assigned id, rather than relying on the root widget being a screenmanager.
FWIW: If the switch code is only going to change screens I would move those single lines into KV.
import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
class Wid(BoxLayout): # Change to layout
def settxt(self, i):
lab = self.ids['lab']
but = self.ids['but']
lab.text = "Label Number {}".format(i)
but.text = "Button Number {}".format(i)
class Win1(Screen):
i = 0
def addw(self):
box1 = self.ids['box1']
self.i = self.i + 1
w = Wid()
w.settxt(self.i)
box1.add_widget(w)
#staticmethod
def switch():
app = App.get_running_app()
app.root.ids.sm.current = "win2"
class Win2(Screen):
#staticmethod
def switch():
app = App.get_running_app()
app.root.ids.sm.current = "win1"
class WidgetQ1App(App):
def build(self):
return Builder.load_file('widgetq.kv')
def on_start(self):
screens = [Win1(name="win1"), Win2(name="win2")]
sm = self.root.ids.sm
for screen in screens:
sm.add_widget(screen)
WidgetQ1App().run()
And the KV code:
<Wid>: # Put widgets in a layout, not a widget.
lab:lab
but:but
BoxLayout:
size: root.size
Label:
id: lab
Button:
id: but
<Win1>
# name:"win1"
box1:box1
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint: 1,0.2
Button:
text:"window 2"
on_release:
root.switch()
Button:
text:"add wid"
on_release:
root.addw()
ScrollView:
GridLayout:
id:box1
orientation: "vertical"
spacing: 2
size_hint_y: None
height: self.minimum_height
row_default_height: 60
cols:1
<Win2>:
# name: "win2"
BoxLayout:
Button:
text:"window 2"
on_release:
root.switch()
BoxLayout:
ScreenManager:
id: sm
<win2>
name: "win2"
size_hint_y: None
height: bl.minimum_height
BoxLayout:
id: bl
Button:
text:"window 2"
on_release:
root.switch()
Your custom widgets don't have a height defined, try changing to something like the above.
Also, start your class names with an upper case letter, kv requires this in some cases. For instance, win2 should be Win2.
A number of issues here, see the comments. The biggest problem I see is putting items in a widget. Put Widgets in a layout, not other widgets.
import kivy
kivy.require('1.0.6')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
kv = """
<Wid>: # Put widgets in a layout, not a widget.
lab:lab
but:but
BoxLayout:
size: root.size
Label:
id: lab
Button:
id: but
<Win1>
# name:"win1"
box1:box1
BoxLayout:
orientation: "vertical"
BoxLayout:
size_hint: 1,0.2
Button:
text:"window 2"
on_release:
root.switch()
Button:
text:"add wid"
on_release:
root.addw()
ScrollView:
GridLayout:
id:box1
orientation: "vertical"
spacing: 2
size_hint_y: None
height: self.minimum_height
row_default_height: 60
cols:1
<Win2>:
# name: "win2"
BoxLayout:
Button:
text:"window 2"
on_release:
root.switch()
ScreenManager:
id: sm
Win1:
name: 'win1'
Win2:
name: 'win2'
"""
class Wid(BoxLayout): # Change to layout
def settxt(self,i):
lab = self.ids['lab']
but = self.ids['but']
lab.text = "Label Number {}".format(i)
but.text = "Button Number {}".format(i)
class Win1(Screen):
i = 0
def addw(self):
box1 = self.ids['box1']
self.i = self.i + 1
w = Wid()
w.settxt(self.i)
box1.add_widget(w)
#staticmethod
def switch():
app = App.get_running_app()
app.root.current = "win2"
class Win2(Screen):
#staticmethod
def switch():
app = App.get_running_app()
app.root.current = "win1"
# class WindowManager(ScreenManager):
# pass
# kv = Builder.load_file("test.kv")
# sm = WindowManager()
#
# screens = [win1(name="win1"), win2(name="win2")]
# for screen in screens:
# sm.add_widget(screen)
#
# sm.current = "win1"
class WidgetQApp(App):
def build(self):
return Builder.load_string(kv)
WidgetQApp().run()
i want to create the ScreenManager in the kv file, but i also need th change the shown screen in the .py file. Thats because i have to create some buttons
dynamically and bind a specific function to them, which will change to a specific (button related) screen. Creating the buttons is way more convient in python. So the main question is: how to access the screenmanager created in a kv file through the py file?
To explain it a bit futher, here is some code:
kv file
#: kivy 1.10.1
ScreenManager:
id: screen_manager
FirstScreen:
id: first_screen
name: 'FirstScreen'
manager: 'screen_manager'
SecondScreen:
id: second_screen
name: 'SecondScreen'
manager: 'screen_manager'
py file
from kivy.modules import console
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import ObjectProperty
class FirstScreen(Screen):
MenuScreen = ObjectProperty(None)
def SwitchToSecond(self):
print(ScreenManagement.current)
ScreenManagement.current = "TestScreen"
class SecondScreen(Screen):
pass
class testApp(App):
pass
if __name__ == "__main__":
testApp().run()
thank you for any guidance in advance
If you want to access the ScreenManager within a Screen you must use its manager attribute, but for this you must not create a property with the same name, in your case you are doing it which is considered a bad practice.
Modifying your code and adding some elements we obtain the following example:
*.kv
#: kivy 1.10.1
ScreenManager:
id: screen_manager
FirstScreen:
id: first_screen
name: 'FirstScreen'
Button:
text: "First"
on_press: first_screen.SwitchToSecond()
SecondScreen:
id: second_screen
name: 'SecondScreen'
Label:
text: "second"
.*py
from kivy.modules import console
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.properties import ObjectProperty
class FirstScreen(Screen):
MenuScreen = ObjectProperty(None)
def SwitchToSecond(self):
self.manager.current = "SecondScreen"
class SecondScreen(Screen):
pass
class testApp(App):
pass
if __name__ == "__main__":
testApp().run()
Here is a simple example using the ScreenManager (I also added a method inside of the MyScreenManager class that accepts a value, which would correspond to the name of the screen you would like to change to, but not necessary for this app to run):
Python
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class Screen1(Screen):
pass
class Screen2(Screen):
pass
class Screen3(Screen):
pass
class MyScreenManager(ScreenManager):
def changescreen(self, value):
self.current = value
#Main application
class TestApp(App):
def build(self):
self.sm = MyScreenManager()
return self.sm
if __name__ == '__main__':
TestApp().run()
kv
<MyScreenManager>:
Screen1:
name: 'screen1'
Screen2:
name: 'screen2'
Screen3:
name: 'screen3'
<Screen1>:
GridLayout:
rows: 2
padding: 20
spacing: 20
Button:
text: 'Go to Screen 2'
on_press: root.manager.current = 'screen2'
Button:
text: 'Go to Screen 3'
on_press: root.manager.current = 'screen3'
Label:
text: 'You are on ' + root.name
<Screen2>:
GridLayout:
rows: 2
padding: 20
spacing: 20
Button:
text: 'Go to Screen 1'
on_press: root.manager.current = 'screen1'
Button:
text: 'Go to Screen 3'
on_press: root.manager.current = 'screen3'
Label:
text: 'You are on ' + root.name
<Screen3>:
GridLayout:
rows: 2
padding: 20
spacing: 20
Button:
text: 'Go to Screen 1'
on_press: root.manager.current = 'screen1'
Button:
text: 'Go to Screen 2'
on_press: root.manager.current = 'screen2'
Label:
text: 'You are on ' + root.name
I am trying to update a field that exists in another screen but am not succeeding.
I would be very very pleased when someone could tell me what I am doing wrong here.
myscreenskv.py:
style = r'''
# File: myscreenskv.py
#: import myscreens myscreens
<ScreenManagement>:
MainScreen:
Screen1:
Screen2:
<MainScreen>:
name: 'main'
mainlog:mainlog
id: scrmain
BoxLayout:
orientation: "vertical"
Label:
text: "Main"
Label:
id: mainlog
Button:
text: "go to screen 1"
on_press:
app.root.current = "screen1"
root.action1()
Button:
text: "go to screen 2"
on_press:
app.root.current = "screen2"
root.action2()
<Screen1>:
name: 'screen1'
sc1log:sc1log
id: scr1
BoxLayout:
orientation: "vertical"
Label:
text: "Screen1"
Label:
id: sc1log
Button:
text: "go to main screen"
on_press: app.root.current = "main"
Button:
text: "go to screen 2"
on_press: app.root.current = "screen2"
<Screen2>:
name: 'screen2'
id: scr2
sc2log:sc2log
BoxLayout:
orientation: "vertical"
Label:
text: "Screen2"
Label:
id: sc2log
Button:
text: "go to main screen"
on_press: app.root.current = "main"
Button:
text: "go to screen 1"
on_press: app.root.current = "screen1"
'''
.py:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from myscreenskv import style
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
def action1(self):
self.ids.scr1.sc1log.text = 'Coming from main'
def action2(self):
self.ids.scr2.sc2log.text = 'Coming from main'
class Screen1(Screen):
def __init__(self, **kwargs):
super(Screen1, self).__init__(**kwargs)
def action1(self):
self.ids.main.mainlog.text = 'Coming from screen1'
def action2(self):
self.ids.scr2.sc2log.text = 'Coming from screen1'
class Screen2(Screen):
def __init__(self, **kwargs):
super(Screen2, self).__init__(**kwargs)
def action1(self):
self.ids.main.mainlog.text = 'Coming from screen2'
def action2(self):
self.ids.scr1.sc1log.text = 'Coming from screen2'
class MyscreensApp(App):
def build(self):
Builder.load_string(style)
sm = ScreenManager()
sm.add_widget(MainScreen())
sm.add_widget(Screen1())
sm.add_widget(Screen2())
sm.current = 'main'
return sm
if __name__ == '__main__':
MyscreensApp().run()
You are trying to access ids dictionary, that's nice, yet in a completely different instance, that's why this error:
AttributeError: 'super' object has no attribute '__getattr__'
You need to access the right instance, to be able to access its properties, which in your case you need to access the ScreenManager, to access its screens property (a list of instances), from which you can do the desired edits of for example text:
MainScreen.action1():
self.manager.screens[1].sc1log.text = 'Coming from main'
# no ids, because you put it into a variable before
To understand why it works let's look at the widget tree:
<MainScreen>:
id: scrmain
BoxLayout:
Label:
Label:
id: mainlog
Button:
Button:
here the ids are a dictionary in MainScreen accessible from MainScreen().ids(an instance) and this is the output:
{'mainlog': <WeakProxy to <kivy.uix.label.Label object at 0x12345678>>}
which means you can't really assign the root widget to its own dictionary - at least not this way + makes no sense anyway, because you can just call root, which gives you the instance of the root widget.
Using the Kivy Screen Manager, I create two Screens. Whilst being in screen 1, i want to change a label in screen two. I highlight the problematic area in my code:
my test.ky:
#: import ScreenManager kivy.uix.screenmanager.ScreenManager
#: import Screen kivy.uix.screenmanager.ScreenManager
#: import SettingsScreen screen
ScreenManager:
MenuScreen:
SettingsScreen:
<MenuScreen>:
name: 'MenuScreen'
BoxLayout:
Button:
text: 'Goto nn'
on_press:
root.manager.current = 'SettingsScreen'
root.change_text()
<SettingsScreen>:
name: 'SettingsScreen'
label_id: label_field
BoxLayout:
Label:
id: label_field
text: "to_be_changed"
and my screen.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
class MenuScreen(Screen):
def change_text(self):
pass
# HERE: something like
# root.SettingsScreen.label_field.text = 'new text'
class SettingsScreen(Screen):
pass
class TestApp(App):
pass
TestApp().run()
Any help is greatly appreciated!
Thanks, Nico
How about this:
When you press the button on MenuScreen, it sets an attribute on itself containing the text you want to put in the SettingsScreen Label. Then the MenuScreen is assigned an id value in the kv file, which is used to reference this attribute. Example:
main.py
class MenuScreen(Screen):
text = StringProperty('')
def change_text(self):
self.text = "The text you want to set"
self.manager.current = "SettingsScreen"
class SettingsScreen(Screen):
label_text = StringProperty('')
kv file
ScreenManager:
id: screen_manager
MenuScreen:
id: menu_screen
name: 'MenuScreen'
manager: screen_manager
SettingsScreen:
name: 'SettingsScreen'
manager: screen_manager
label_text: menu_screen.text
<MenuScreen>:
BoxLayout:
Button:
text: 'Goto nn'
on_press:
root.change_text()
<SettingsScreen>:
BoxLayout:
Label:
text: root.label_text
As you can see, I set the names and id of the screens under ScreenManager itself in the kv file, as this is what I would usually do to make this work.