Kivy Python edit Label text from another class
Question:
I have two screens.
The first screen has a "Play" button that sends me to the "PlayScreen".
The second screen has a Label and two buttons;
Button "NewRandom": loads a random number from SomeApp.RandomGen()
,
Button "Clear": Clears
What I would like to happen is that initiate_random_number()
executes as soon as the buttons are created.
However, App.get_running_app().root.ids.play_screen.random_num.text
is None
because I’m guessing some ids dictionary under the hood is still not built?
Is there anyway I can access the Label from this RandomNumber
class?
thanks.
Python app:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
import numpy as np
class MainWindow(Screen):
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
class PlayScreen(Screen):
def __init__(self, *args, **kwargs):
super(PlayScreen, self).__init__(*args, **kwargs)
class WindowManager(ScreenManager):
def __init__(self, **kwargs):
super(WindowManager, self).__init__(**kwargs)
main_window = ObjectProperty(None)
play_screen = ObjectProperty(None)
class RandomNumber(GridLayout):
def __init__(self, *args, **kwargs):
super(RandomNumber, self).__init__(*args, **kwargs)
self.cols = 2
self.add_widget(Button(text='NewRandom', on_release=self.on_release))
self.add_widget(Button(text='Clear', on_release=self.on_release))
def initiate_random_number(self):
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
def on_release(self, btn):
if btn.text == 'NewRandom':
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
else:
App.get_running_app().root.ids.play_screen.random_label.text = ''
#kv = Builder.load_file('sample.kv')
class SampleApp(App):
def __init__(self, **kwargs):
super(SampleApp, self).__init__(**kwargs)
def build(self):
sm = WindowManager()
return sm
def RandomGen(self):
return np.random.randint(100)
if __name__ == '__main__':
SampleApp().run()
kv:
<WindowManager>:
id: window_manager
main_window: main_window
play_screen: play_screen
MainWindow:
id: main_window
name: "main_window"
manager: window_manager
PlayScreen:
id: play_screen
name: "play_screen"
manager: window_manager
<MainWindow>:
BoxLayout:
orientation: "vertical"
Button:
text: "Play"
on_release:
app.root.current = "play_screen"
root.manager.transition.direction = "left"
<PlayScreen>:
random_label: random_label
BoxLayout:
orientation: "vertical"
Label:
id: random_label
#text: #TODO: show the output of initiate_random_number or Button
RandomNumber:
Button:
text: "Back!"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
the solution should give me a way to call the random_label
via python and not just Kivy.
Answers:
If you want initiate_random_number()
to run before the PlayScreen
Buttons
are displayed (although your code only has one Button
), you can define an on_enter()
method in the PlayScreen
class:
def on_enter(self, *args):
RandomNumber.initiate_random_number()
However, this requires a couple other changes. Some methods need to redefined as static
and the access to the random_label
must be corrected:
@staticmethod
def initiate_random_number():
random_num = str(SomeApp.RandomGen())
App.get_running_app().root.get_screen('play_screen').ids.random_label.text = random_num
Another method in the App
that needs to be static:
@staticmethod
def RandomGen():
return np.random.randint(100)
Formalising @John Anderson solution above:
Python:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
import numpy as np
class MainWindow(Screen):
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
class PlayScreen(Screen):
def __init__(self, *args, **kwargs):
super(PlayScreen, self).__init__(*args, **kwargs)
def on_enter(self, *args):
RandomNumber.initiate_random_number()
class WindowManager(ScreenManager):
def __init__(self, **kwargs):
super(WindowManager, self).__init__(**kwargs)
# main_window = ObjectProperty(None)
# play_screen = ObjectProperty(None)
class RandomNumber(GridLayout):
def __init__(self, *args, **kwargs):
super(RandomNumber, self).__init__(*args, **kwargs)
self.cols = 2
self.add_widget(Button(text='NewRandom', on_release=self.on_release))
self.add_widget(Button(text='Clear', on_release=self.on_release))
@staticmethod
def initiate_random_number():
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
def on_release(self, btn):
if btn.text == 'NewRandom':
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
else:
App.get_running_app().root.ids.play_screen.random_label.text = ''
#kv = Builder.load_file('sample.kv')
class SampleApp(App):
def __init__(self, **kwargs):
super(SampleApp, self).__init__(**kwargs)
def build(self):
sm = WindowManager()
return sm
@staticmethod
def RandomGen():
return np.random.randint(100)
if __name__ == '__main__':
SampleApp().run()
kv:
<WindowManager>:
id: window_manager
main_window: main_window
play_screen: play_screen
MainWindow:
id: main_window
name: "main_window"
manager: window_manager
PlayScreen:
id: play_screen
name: "play_screen"
manager: window_manager
<MainWindow>:
BoxLayout:
orientation: "vertical"
Button:
text: "Play"
on_release:
app.root.current = "play_screen"
root.manager.transition.direction = "left"
<PlayScreen>:
random_label: random_label
BoxLayout:
orientation: "vertical"
Label:
id: random_label
#text: #TODO: show the output of initiate_random_number or Button
RandomNumber:
Button:
text: "Back!"
on_release:
app.root.current = "main_window"
root.manager.transition.direction = "right"
I have two screens.
The first screen has a "Play" button that sends me to the "PlayScreen".
The second screen has a Label and two buttons;
Button "NewRandom": loads a random number from SomeApp.RandomGen()
,
Button "Clear": Clears
What I would like to happen is that initiate_random_number()
executes as soon as the buttons are created.
However, App.get_running_app().root.ids.play_screen.random_num.text
is None
because I’m guessing some ids dictionary under the hood is still not built?
Is there anyway I can access the Label from this RandomNumber
class?
thanks.
Python app:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
import numpy as np
class MainWindow(Screen):
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
class PlayScreen(Screen):
def __init__(self, *args, **kwargs):
super(PlayScreen, self).__init__(*args, **kwargs)
class WindowManager(ScreenManager):
def __init__(self, **kwargs):
super(WindowManager, self).__init__(**kwargs)
main_window = ObjectProperty(None)
play_screen = ObjectProperty(None)
class RandomNumber(GridLayout):
def __init__(self, *args, **kwargs):
super(RandomNumber, self).__init__(*args, **kwargs)
self.cols = 2
self.add_widget(Button(text='NewRandom', on_release=self.on_release))
self.add_widget(Button(text='Clear', on_release=self.on_release))
def initiate_random_number(self):
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
def on_release(self, btn):
if btn.text == 'NewRandom':
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
else:
App.get_running_app().root.ids.play_screen.random_label.text = ''
#kv = Builder.load_file('sample.kv')
class SampleApp(App):
def __init__(self, **kwargs):
super(SampleApp, self).__init__(**kwargs)
def build(self):
sm = WindowManager()
return sm
def RandomGen(self):
return np.random.randint(100)
if __name__ == '__main__':
SampleApp().run()
kv:
<WindowManager>:
id: window_manager
main_window: main_window
play_screen: play_screen
MainWindow:
id: main_window
name: "main_window"
manager: window_manager
PlayScreen:
id: play_screen
name: "play_screen"
manager: window_manager
<MainWindow>:
BoxLayout:
orientation: "vertical"
Button:
text: "Play"
on_release:
app.root.current = "play_screen"
root.manager.transition.direction = "left"
<PlayScreen>:
random_label: random_label
BoxLayout:
orientation: "vertical"
Label:
id: random_label
#text: #TODO: show the output of initiate_random_number or Button
RandomNumber:
Button:
text: "Back!"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
the solution should give me a way to call the random_label
via python and not just Kivy.
If you want initiate_random_number()
to run before the PlayScreen
Buttons
are displayed (although your code only has one Button
), you can define an on_enter()
method in the PlayScreen
class:
def on_enter(self, *args):
RandomNumber.initiate_random_number()
However, this requires a couple other changes. Some methods need to redefined as static
and the access to the random_label
must be corrected:
@staticmethod
def initiate_random_number():
random_num = str(SomeApp.RandomGen())
App.get_running_app().root.get_screen('play_screen').ids.random_label.text = random_num
Another method in the App
that needs to be static:
@staticmethod
def RandomGen():
return np.random.randint(100)
Formalising @John Anderson solution above:
Python:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
import numpy as np
class MainWindow(Screen):
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
class PlayScreen(Screen):
def __init__(self, *args, **kwargs):
super(PlayScreen, self).__init__(*args, **kwargs)
def on_enter(self, *args):
RandomNumber.initiate_random_number()
class WindowManager(ScreenManager):
def __init__(self, **kwargs):
super(WindowManager, self).__init__(**kwargs)
# main_window = ObjectProperty(None)
# play_screen = ObjectProperty(None)
class RandomNumber(GridLayout):
def __init__(self, *args, **kwargs):
super(RandomNumber, self).__init__(*args, **kwargs)
self.cols = 2
self.add_widget(Button(text='NewRandom', on_release=self.on_release))
self.add_widget(Button(text='Clear', on_release=self.on_release))
@staticmethod
def initiate_random_number():
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
def on_release(self, btn):
if btn.text == 'NewRandom':
random_num = str(SampleApp.RandomGen())
App.get_running_app().root.ids.play_screen.random_label.text = random_num
else:
App.get_running_app().root.ids.play_screen.random_label.text = ''
#kv = Builder.load_file('sample.kv')
class SampleApp(App):
def __init__(self, **kwargs):
super(SampleApp, self).__init__(**kwargs)
def build(self):
sm = WindowManager()
return sm
@staticmethod
def RandomGen():
return np.random.randint(100)
if __name__ == '__main__':
SampleApp().run()
kv:
<WindowManager>:
id: window_manager
main_window: main_window
play_screen: play_screen
MainWindow:
id: main_window
name: "main_window"
manager: window_manager
PlayScreen:
id: play_screen
name: "play_screen"
manager: window_manager
<MainWindow>:
BoxLayout:
orientation: "vertical"
Button:
text: "Play"
on_release:
app.root.current = "play_screen"
root.manager.transition.direction = "left"
<PlayScreen>:
random_label: random_label
BoxLayout:
orientation: "vertical"
Label:
id: random_label
#text: #TODO: show the output of initiate_random_number or Button
RandomNumber:
Button:
text: "Back!"
on_release:
app.root.current = "main_window"
root.manager.transition.direction = "right"