I want to create a list of coloured labels. The thing is that I could do it with the kv file, but I need to do it through the build() method. So I tried replicate what I have done, but it does not work. And I can't understand why.
This is what I've coded
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.graphics import *
class RL(RelativeLayout): # Creates the background colour for each label
def __init__(self, **kwargs):
super().__init__(**kwargs)
with self.canvas:
Color(.7, 0, .5, 1)
Rectangle(size_hint=self.size)
class MainMenu(BoxLayout):
N_LBLS = 8
labels_text = []
RL_list = []
def __init__(self, **kwargs):
super().__init__(**kwargs)
button = Button(text='do something')
button.bind(on_release=self.change_text)
box = BoxLayout(orientation='vertical', padding= 10, spacing = 15)
for i in range(0, self.N_LBLS):
self.RL_list.append(RL())
self.labels_text.append(Label(text=f'{i}º label', size_hint=self.size))
self.RL_list[i].add_widget(self.labels_text[i])
box.add_widget(self.RL_list[i])
self.add_widget(button)
self.add_widget(box)
def change_text(self, instance):
for lbl in self.labels_text:
if lbl.text[0] == '5':
lbl.text = 'Text changed'
class MainApp(App):
def build(self):
return MainMenu()
if __name__ == '__main__':
MainApp().run()
It's supposed to make a button to the left, and a list of 8 coloured labels to the right.
The problem is that you are setting size_hint=self.size in each Label. The self.size is the size of the MainMenu, which is [100,100] when that code is executed. Note that size_hint is a multiplier that is applied to the parents size to calculate the widgets size. So a size_hint of [100,100] makes each Label 100 times bigger than the MainMenu. So your code is working, but the Labels are so large that the text is off the screen. Start by just removing size_hint=self.size.
And, to set a background color on a Label, you can just use the canvas of that Label, rather than some container. Here is a version of your code that does that:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
class ColorLabel(Label):
pass
Builder.load_string('''
<ColorLabel>:
bg_color: [.7, 0, .5, 1]
canvas.before:
Color:
rgba: self.bg_color
Rectangle:
pos: self.pos
size: self.size
''')
class MainMenu(BoxLayout):
N_LBLS = 8
labels_text = []
def __init__(self, **kwargs):
super().__init__(**kwargs)
button = Button(text='do something')
button.bind(on_release=self.change_text)
box = BoxLayout(orientation='vertical', padding=10, spacing=15)
for i in range(0, self.N_LBLS):
self.labels_text.append(ColorLabel(text=f'{i}º label'))
box.add_widget(self.labels_text[i])
self.add_widget(button)
self.add_widget(box)
def change_text(self, instance):
for lbl in self.labels_text:
if lbl.text[0] == '5':
lbl.text = 'Text changed'
lbl.bg_color = [0, 1, 0, 1]
class MainApp(App):
def build(self):
return MainMenu()
if __name__ == '__main__':
MainApp().run()
I have a screen manager ThirdWindow which is supposed to change the screen when B1 is clicked basically a navigation thing. Please note ThirdWindow is a a different class. callback is called when B1 is clicked. it changes the screen with the help of ThirdWindow I think. I used self.manager.current it didn't worked, I also tried using it by making ThirdWindow a def in class Dre but the results were same. The print statement is not getting printed that is inside def callback(self, instance) so I think the def is not getting called on_click at all. How can I fix that? Thanks
import kivy
from kivy.app import App
from kivy.core.audio import SoundLoader
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.graphics import Rectangle
from kivy import platform
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
pass
class ThirdWindow(ScreenManager):
def load(self):
sm = ScreenManager
sm.add_widget(Dre(name='Dre'))
sm.add_widget(SecondWindow(name='SecondWindow'))
self.sm.current = 'Dre'
class Dre(RelativeLayout):
def __init__(self, **kwargs):
super(Dre, self).__init__(**kwargs)
self.color = [254/255, 102/255, 37/255, 1]
self.H_color = [254/255, 102/255, 37/255]
self.sound_theme = None
self.init_audio()
self.kv = Builder.load_file('Levels.py')
if platform in ('linux', 'win', 'macosx'):
with self.canvas.before:
self.bg = Rectangle(size=self.size, source='Neo.png')
self.bind(pos=self.update_bg)
self.bind(size=self.update_bg)
else:
with self.canvas.before:
self.bg = Rectangle(size=self.size, source='Neon.png')
self.bind(pos=self.update_bg)
self.bind(size=self.update_bg)
def update_bg(self, *args):
if platform in ('linux', 'win', 'macosx'):
self.bg.pos = self.pos
self.bg.size = self.size
self.add_widget(Label(text='D R E A M S',
pos_hint={'center_x': .5, 'center_y': .8},
font_size='60dp', font_name='Roboto-Bold.ttf', color=self.H_color))
B1 = Button(text='P L A Y', font_name='Roboto-Bold.ttf', size_hint=(.2, .15),
pos_hint={'center_x': .5, "center_y": .3}, background_color = self.color, background_normal='')
# B1.bind(on_press=return self.kv)
self.add_widget(B1)
else:
self.bg.pos = self.pos
self.bg.size = self.size
self.add_widget(Label(text='D R E A M S',
pos_hint={'center_x': .5, 'center_y': .8},
font_size='30dp', font_name='Roboto-Bold.ttf', color=self.H_color))
B1 = Button(text='P L A Y', font_name='Roboto-Bold.ttf', size_hint=(.2, .15),
pos_hint={'center_x': .5, "center_y": .3}, background_color=self.color, background_normal='',
on_press=self.callback)
self.add_widget(B1)
def callback(self, instance):
print('working')
self.manager.current = 'SecondWindow'
def init_audio(self):
self.sound_theme = SoundLoader.load('Bg_theme.mp3')
self.sound_theme.volume = 1
self.sound_theme.loop = True
if self.sound_theme:
self.sound_theme.play()
print('okay')
else:
print('not okay')
class SecondWindow(Screen):
def __init__(self, **kwargs):
super(SecondWindow, self).__init__(**kwargs)
self.color = [254 / 255, 102 / 255, 37 / 255, 1]
if platform in ('linux', 'win', 'macosx'):
with self.canvas.before:
self.bg = Rectangle(size=self.size, color=self.color)
class LabApp(App):
def build(self):
return Dre()
if __name__ == '__main__':
LabApp().run()```
if you provide any solution please provide it in .py file.
Many issues with your code.
First, you have defined a ScreenManager class (ThirdWindow), but you have not created an instance of it or included it in your GUI. In order to use a ScreenManager to manage Screens, you must add it to your GUI. I would suggest modifying your LabApp class to use ThirdWindow:
class LabApp(App):
def build(self):
return ThirdWindow()
and modify ThirdWindow to replace the load() method with an __init__() method:
class ThirdWindow(ScreenManager):
def __init__(self, **kwargs):
super(ThirdWindow, self).__init__(**kwargs)
self.add_widget(Dre(name='Dre'))
self.add_widget(SecondWindow(name='SecondWindow'))
Since the Dre class is being used as a Screen, it must be redefined as a Screen:
class Dre(Screen):
and you can add the callback to the creation of the B1 Button:
B1 = Button(text='P L A Y', font_name='Roboto-Bold.ttf', size_hint=(.2, .15), on_release=self.callback,
pos_hint={'center_x': .5, "center_y": .3}, background_color = self.color, background_normal='')
I am making kivy app, something like project manager. I've got problem, i'll try to describe it.
In my app you can create new "project" by pressing button, then open the project and create some task. I need to store "project" into list or dictioniares. I've been thinking about this problem whole week and I can't solve. Do you have any ideas? I include my py. file and my kv. file here.
If you have some improvments to my codes, come here with them.
My python file:
from kivy.app import App
import sys
from kivy.storage.jsonstore import JsonStore
from kivy.uix.screenmanager import ScreenManager,Screen, SlideTransition, RiseInTransition
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.checkbox import CheckBox
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.behaviors import ButtonBehavior
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.image import Image
from kivy.uix.checkbox import CheckBox
from kivy.core.window import Window
from kivy.graphics import Color, Ellipse, Rectangle, Line
from kivy.uix.spinner import Spinner
from kivy.uix.stencilview import StencilView
Window.size = (400, 650)
Window.clearcolor = (0,0,0,0)
kv = Builder.load_file('main.kv')
c = 0
class MS(Screen, Widget):
def on_exit(self):
sys.exit()
class SES(Screen):
pass
class OPS(Screen, BoxLayout):
themes = ["DARK","LIGHT"]
def __init__(self, **kwargs):
super(OPS, self).__init__(**kwargs)
label = Label(text="COLOR THEME:", size_hint=(.2,.1), pos_hint={"x":.25,"top":.9})
self.add_widget(label)
tgbt = ToggleButton(text="DARK", size_hint=(.2, .1), pos_hint={"x":.5,"top":.9},background_normal="",background_color =(0,0,0,0))
self.add_widget(tgbt)
tgbt2 = ToggleButton(text="LIGHT", size_hint=(.2, .1), pos_hint={"x": .7, "top": .9},background_normal="", background_color= (1,1,1,1))
self.add_widget(tgbt2)
class PRS(Screen, BoxLayout):
widgets1 = []
l1x = .1
l1top = .87
txt1x = .4
txt1top = .88
ck1x = .64
ck1top = .88
chtop = 0.88
deltop = 0.88
projects = []
def changer(self,*args):
self.manager.current = 'task'
def changer2(self, *args):
self.manager.current = 'main'
def new_pr(self, *args):
txt1 = TextInput(multiline=False,size_hint=(0.3,0.05), pos_hint={'x':self.txt1x,"top":self.txt1top})
self.add_widget(txt1)
label1 = Label(text="YOUR PROJECT NAME:",size_hint=(0.2,0.04),pos_hint={"x":self.l1x,"top":self.l1top})
self.add_widget(label1)
check1 = CheckBox(active=False, size_hint=(0.2,0.05), pos_hint={"x":self.ck1x,"top":self.ck1top})
self.add_widget(check1)
print(self.projects)
self.widgets1.append(check1)
self.widgets1.append(label1)
self.widgets1.append(txt1)
self.l1top = self.l1top - .07
self.txt1top = self.txt1top - .07
self.ck1top = self.ck1top - .07
spinner = Spinner(text="OPTIONS", values="DELETE",background_normal="",background_color =(200/255.0, 194/255.0, 136/255.0,1))
button = Button(text="OPEN",color=(200 / 255.0, 194 / 255.0, 136 / 255.0, 1), size_hint=(0.1,0.05), pos_hint={"x":0.77, "top":self.chtop})
self.add_widget(button)
self.widgets1.append(button)
button2 = Button(text = "DELETE",color=(200 / 255.0, 194 / 255.0, 136 / 255.0, 1), size_hint=(0.13,0.05), pos_hint={"x":0.87,"top":self.deltop})
self.add_widget(button2)
self.widgets1.append(button2)
self.chtop = self.chtop - 0.07
self.deltop = self.deltop - 0.07
button.bind(on_press= self.changer)
button2.bind(on_release= self.remover)
def remover(self, *args):
for i in self.widgets1:
self.remove_widget(i)
self.l1top = .88
self.deltop = .88
self.chtop = .88
self.ck1top = .88
self.txt1top = .88
def __init__(self, **kwargs):
super(PRS, self).__init__(**kwargs)
bt1 = (Button(text="NEW PROJECT",pos_hint={"x":.0,"top":1},size_hint=(.5,.1)))
self.add_widget(bt1)
bt2 = (Button(text="BACK",pos_hint={"x":.5,"top":1},size_hint=(.5,.1)))
self.add_widget(bt2)
bt1.bind(on_release=self.new_pr)
bt2.bind(on_release=self.changer2)
def clear_screen(self):
self.canvas.clear()
class TASKS(Screen, BoxLayout):
task1 = []
tinpx = 0.25
tinptop = .83
chkx = 0.76
chktop = .84
showed = False
def note(self, *args):
self.showed = True
if self.showed == True:
textinput = TextInput(multiline=True,size_hint=(.4,.5), pos_hint={"x":0.56,"top":self.chktop-0.1})
self.add_widget(textinput)
while self.showed == False:
self.remove_widget(textinput)
break
def change(self, *args):
self.showed = False
def changer(self,*args):
self.manager.current = 'project'
def new_task(self, *args):
txt1 = TextInput(multiline=False, size_hint=(.2,.04), pos_hint={"x":self.tinpx, "top":self.tinptop})
self.add_widget(txt1)
chck1 = CheckBox(active=False, size_hint = (.2, .05), pos_hint = {"x":self.chkx,"top":self.chktop})
self.add_widget(chck1)
notes = Button(text="NOTES", color=(200 / 255.0, 194 / 255.0, 136 / 255.0, 1), size_hint=(.2,.05), pos_hint={"x":0.56,"top":self.chktop})
notes.bind(on_press=self.note)
notes.bind(on_release=self.change)
self.add_widget(notes)
self.tinptop = self.tinptop - .07
self.chktop = self.chktop - .07
def __init__(self, **kwargs):
super(TASKS, self).__init__(**kwargs)
self.add_widget(Label(text="TASK NAME", size_hint=(.2,.04), pos_hint={"x":0.25,"top":.88}))
self.add_widget(Label(text="COMPLETE", size_hint = (.2,.04), pos_hint={"x":0.75,"top":.88}))
bt1 = Button(text="NEW TASK",color=(0,0,0),size_hint=(.5,.1), pos_hint = {"x":0, "top":1},background_normal="",background_color =(200/255.0, 194/255.0, 136/255.0,1))
self.add_widget(bt1)
homebt = Button(text="BACK",color=(0,0,0),size_hint=(.5, .1), pos_hint={"x":0.5,"top":1},background_normal="",background_color =(200/255.0, 194/255.0, 136/255.0,1))
self.add_widget(homebt)
homebt.bind(on_release=self.changer)
bt1.bind(on_release=self.new_task)
class Help(Screen, Widget):
pass
class MApp(App):
title = "PROJECT MANAGER"
def build(self):
wid = PRS(size_hint=(None, None), size=Window.size)
sm = ScreenManager()
sm.add_widget(MS(name = "main"))
sm.add_widget(SES(name = "second"))
sm.add_widget(OPS(name = "options"))
sm.add_widget(PRS(name="project"))
sm.add_widget(TASKS(name="task"))
sm.add_widget(Help(name="help"))
return sm
if __name__ == "__main__":
MApp().run()
My kv. file:
<MS>:
GridLayout:
cols:7
GridLayout:
cols:2
Button:
text : "NEW"
color:0,0,0
on_release:app.root.current="project"
background_normal:""
background_color:(200/255.0, 194/255.0, 136/255.0,1)
Button:
text : "OPTIONS"
color:0,0,0
on_release:app.root.current="options"
background_normal:""
background_color:(200/255.0, 194/255.0, 136/255.0,1)
Button:
text : "LOAD"
color:0,0,0
on_release:app.root.current="second"
background_normal:""
background_color:(200/255.0, 194/255.0, 136/255.0,1)
Button:
text : "HELP"
color:0,0,0
on_release:app.root.current="help"
background_normal:""
background_color:(200/255.0, 194/255.0, 136/255.0,1)
Button:
text : "Next"
color:0,0,0
on_release:app.root.current="second"
background_normal:""
background_color:(200/255.0, 194/255.0, 136/255.0,1)
Button:
id:bt1
text : "Exit"
color:0,0,0
background_normal:""
background_color:(200/255.0, 194/255.0, 136/255.0,1)
on_release:app.stop()
<SES>:
name:"second"
Button:
text:"back"
color:0,0,0
on_release:
app.root.current="main"
<OPS>:
name:"options"
BoxLayout:
Button:
size_hint:.5,.2
pos_hint : {"x":.5,"top":.15}
text: "HOME"
color:0,0,0
on_release:app.root.current="main"
<PRS>:
name:"project"
<TASKS>:
name:"task"
<Help>:
name:"help"
GridLayout:
Label:
text:"COMING SOON!!!"
color:0,0,0
Thaks for help, time and effort.
Micheno
Here is simple example of my problem.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class Test(BoxLayout):
x1 = 0.2
top1 = 0.9
widgets = []
def adder(self, *args):
lb1 = Label(text="HELLO WORLD", pos_hint={"x":self.x1,"top":self.top1})
self.add_widget(lb1)
self.x1 = self.x1 - 0.05
self.top1 = self.top1 - 0.05
self.widgets.append(lb1)
def remover(self, *args):
for i in self.widgets:
self.remove_widget(i)
self.x1=0.2
self.top1 = 0.9
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
bt1 = Button(text="ADD", pos_hint={"x":.1,"top":1}, size_hint=(0.2,0.4))
self.add_widget(bt1)
removebt = Button(text = "REMOVE",pos_hint={"x":.4,"top":1}, size_hint=(0.2,0.4))
self.add_widget(removebt)
removebt.bind(on_release=self.remover)
bt1.bind(on_release=self.adder)
class APP(App):
def build(self):
return Test()
if __name__ == "__main__":
APP().run()
If i want to delete only one label it will delete all. Just try to copy and run it
Just remove the last Label in the list:
def remover(self, *args):
if len(self.widgets) > 0:
self.remove_widget(self.widgets.pop(-1))
OK i could delete last that's improvement, but my problem is like this. What if I with button "ADD" I add text and button to remove the text and the button itself. Here is my new example with yours improvment.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
Window.size = (400, 650)
class Test(BoxLayout):
x1 = 0.1
top1 = 0.9
widgets = []
def adder(self, *args):
lb1 = Label(text="HELLO WORLD", pos_hint={"x":self.x1,"top":self.top1})
self.add_widget(lb1)
removebt = Button(text = "REMOVE",pos_hint={"x":self.x1-0.1,"top":self.top1}, size_hint=(0.5,0.1))
self.add_widget(removebt)
self.widgets.append(removebt)
removebt.bind(on_release=self.remover)
self.widgets.append(lb1)
self.top1 = self.top1 - 0.05
def remover(self, *args):
if len(self.widgets) > 0:
self.remove_widget(self.widgets.pop(-1))
self.x1=0.2
self.top1 = 0.9
def __init__(self, **kwargs):
super(Test, self).__init__(**kwargs)
bt1 = Button(text="ADD", pos_hint={"x":.1,"top":1}, size_hint=(1,0.4))
self.add_widget(bt1)
bt1.bind(on_release=self.adder)
class APP(App):
def build(self):
return Test()
if __name__ == "__main__":
APP().run()
I am using Kivy library to create an app using mainly Python code. I am newbie in Python and Kivy. Here some snippets of my code.
I was trying to pass an image defined "on_start" to my NavButton. #ikolim helped me out to identify the issue. You can see my comments below.
Widget
class NavButton(GridLayout):
def __init__(self, **kwargs):
super(NavButton, self).__init__(**kwargs)
self.rows = 1
frame = FloatLayout(id = "frame")
grid1 = MyGrid(
rows = 1,
cols = 5,
pos_hint = {"top":1, "left": 1},
size_hint = [1, .2] )
grid1.set_background(0.95,0.95,0.95,1)
grid1.add_widget(MyButton(
source = "img/settings.png",
size_hint = [0.2,0.2] ))
grid1.add_widget(MyButton(
source = "img/arrow-left.png" ))
city_icon = Image(
source="img/image1.png",
id="city_icon",
size_hint=[0.8, 0.8])
self.ids.cityicon = city_icon
grid1.add_widget(city_icon)
grid1.add_widget(MyButton(
source = "img/arrow-right.png" ))
grid1.add_widget(MyButton(
source = "img/globe.png",
size_hint = [0.2,0.2] ))
frame.add_widget(grid1)
self.add_widget(frame)
Screens
class Homescreen(Screen):
def __init__(self, **kwargs):
super(Homescreen, self).__init__(**kwargs)
frame = FloatLayout(id = "frame")
grid1 = NavButton()
frame.add_widget(grid1)
...
Screen Manager
Here is where I was messing up! Apparently you have to define the name of your homescreen (i.e.homescreen = Homescreen(name="home_screen")) otherwise it does not update the image of the NavButton when you start the application. I am not sure why but I just what to highlight this for future coders.
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
homescreen = Homescreen()
self.add_widget(homescreen)
self.ids.screenmanager = self
def change_screen(self, name):
self.current = name
Builder
GUI = Builder.load_file("main.kv")
class Main(App):
def build(self):
return GUI
def on_start(self):
self.mynewimage = "image2"
homescreen = self.root.get_screen("home_screen")
homescreen.ids.navbutton.ids.cityicon.source = f"img/{self.mynewimage}.png"
if __name__ == "__main__":
Main().run()
Again, #ikolim thanks for your support.
Solution 2
The following enhancements are required to solve the problem.
class NavButton()
Replace self.ids.cityicon = "cityicon"
with self.ids.cityicon = city_icon
Delete self.bind(on_start=self.update_image) and method update_image()
Method on_start()
Replace homescreen =
Main.get_running_app().root.get_screen("home_screen") with
homescreen = self.root.get_screen("home_screen")
Replace
frame.children[3].children[0].children[0].children[2].source with
homescreen.ids.navbutton.ids.cityicon.source
Remove lines (frame = homescreen.children[0], navbutton =
frame.children[3], and print(...))
Snippets - py file
class NavButton(GridLayout):
def __init__(self, **kwargs):
super(NavButton, self).__init__(**kwargs)
...
city_icon = Image(
source="img/settings.png",
id="city_icon",
size_hint=[0.8, 0.8])
self.ids.cityicon = city_icon
...
class Main(App):
...
def on_start(self):
self.my_city = "it-Rome"
homescreen = self.root.get_screen("home_screen")
homescreen.ids.navbutton.ids.cityicon.source = f"img/{self.my_city}.png"
...
Example - main.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import ButtonBehavior
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.graphics import Color, Rectangle
class MyButton(ButtonBehavior, Image):
pass
class ImageButton(ButtonBehavior, Image):
pass
### Components
class NavButton(GridLayout):
def __init__(self, **kwargs):
super(NavButton, self).__init__(**kwargs)
self.rows = 1
frame = FloatLayout(id="frame")
grid1 = MyGrid(
rows=1,
cols=5,
pos_hint={"top": 1, "left": 1},
size_hint=[1, .2])
grid1.set_background(0.95, 0.95, 0.95, 1)
grid1.add_widget(MyButton(
source="img/settings.png",
size_hint=[0.2, 0.2]))
grid1.add_widget(MyButton(
source="img/arrow-left.png"))
city_icon = Image(
source="img/settings.png",
id="city_icon",
size_hint=[0.8, 0.8])
self.ids.cityicon = city_icon
grid1.add_widget(city_icon)
grid1.add_widget(MyButton(
source="img/arrow-right.png"))
grid1.add_widget(MyButton(
source="img/globe.png",
size_hint=[0.2, 0.2]))
frame.add_widget(grid1)
self.add_widget(frame)
### Grids
class MyGrid(GridLayout):
def set_background(self, r, b, g, o):
self.canvas.before.clear()
with self.canvas.before:
Color(r, g, b, o)
self.rect = Rectangle(pos=self.pos, size=self.size)
self.bind(pos=self.update_rect,
size=self.update_rect)
def update_rect(self, *args):
self.rect.pos = self.pos
self.rect.size = self.size
### Screens
class Homescreen(Screen):
def __init__(self, **kwargs):
super(Homescreen, self).__init__(**kwargs)
frame = FloatLayout(id="frame")
grid1 = NavButton()
frame.add_widget(grid1)
# This grid contains the number of zpots collected
grid2 = MyGrid(
cols=1,
pos_hint={"top": 0.8, "left": 1},
size_hint=[1, .2], )
grid2.add_widget(Image(
source="img/spot.png"))
grid2.add_widget(Label(
text="[color=3333ff]20/30[/color]",
markup=True))
grid2.set_background(0.95, 0.95, 0.95, 1)
frame.add_widget(grid2)
# This grid contains a scrollable list of nearby zpots
grid3 = MyGrid(
cols=1,
pos_hint={"top": 0.6, "left": 1},
size_hint=[1, .5])
grid3.set_background(0.95, 0.95, 0.95, 1)
frame.add_widget(grid3)
# This grid contains a the map of nearby zpots
grid4 = MyGrid(
cols=1,
pos_hint={"top": 0.1, "left": 1},
size_hint=[1, .1])
grid4.set_background(0.95, 0.95, 0.95, 1)
frame.add_widget(grid4)
self.ids.navbutton = grid1
self.add_widget(frame)
class Newscreen(Screen):
pass
class Settingscreen(Screen):
pass
### ScreenManager
class MyScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(MyScreenManager, self).__init__(**kwargs)
homescreen = Homescreen(name='home_screen')
self.add_widget(homescreen)
self.ids.screenmanager = self
def change_screen(self, name):
self.current = name
class TestApp(App):
def build(self):
return MyScreenManager()
def on_start(self):
self.my_city = "it-Rome"
homescreen = self.root.get_screen("home_screen")
print(f"\non_start-Before change: img={homescreen.ids.navbutton.ids.cityicon.source}")
homescreen.ids.navbutton.ids.cityicon.source = f"img/{self.my_city}.png"
print(f"\non_start-After change: img={homescreen.ids.navbutton.ids.cityicon.source}")
if __name__ == "__main__":
TestApp().run()
Output
Solution 1
Use App.get_running_app() function to get an instance of your application
Add self in-front of my_city
Snippets - py file
class NavButton(GridLayout):
def get(self):
...
city_icon = Image(
source = "img/" + App.get_running_app().my_city,
size_hint = [0.8,0.8] )
...
class Main(App):
def build(self):
return GUI
def on_start(self):
# get data from DB
self.my_city = "it-Rome"