How to use strings in kivy - python-3.x

I want want to use strings from my main python file to the .kv file but don't know what commands to use. I want to put the string in the label text
from kivy.app import App
import kivy.uix.label
import kivy.uix.button
from kivy.uix.boxlayout import BoxLayout
string1 = "hi"
class TestApp(BoxLayout):
pass
class MyApp(App):
def build(self):
return TestApp()
if __name__ == '__main__':
MyApp().run()
<TestApp>
BoxLayout:
Label:
text: 'hi'
I tried searching all over the internet but couldn't find any solutions

I I figured it out. You should add a string property in your class to use that string

Related

how to print all textinputs values in a python/kivy app, added by a for cycle?

I add some TextInputs in a Python3/kivy app, using a for cycle. I'd need to get all updated values after clicking a Button:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
class app(App):
def build(self):
self.box=BoxLayout(orientation='vertical')
for n in range(5):
self.box.add_widget(TextInput())
def doet(instance):
print('values: ')
#print all TextInputs values
self.box.add_widget(Button(text='DOET',on_press=doet))
return self.box
app().run()
def doet(instance):
print('values: ')
# for loop:
for t in instance.parent.children:
if isinstance(t, TextInput):
print(t.text)
# using list comprehension
print('\n'.join([t.text for t in instance.parent.children if isinstance(t, TextInput)]))

Anyone know how to pass an argument defined in a kivy script to a class?

I have two scripts called "test_1.py" and "widgets_1.py". The first one is the main app that uses the standard widgets created in the second script to draw the main app. There is something I am missing because I expected to get a green background (admin = "user") but I didn't.
I looks like MyLabel is created with kivy default values and later on changes its values because I get the screen with the right line_color and line_width stated in "test_1.py".
Anyone knows the right way to pass admin property when initiating the widget from kivy language?
PS. This is a reduced example and being admin or not is used for other purposes than changing the background.
test_1.py:
import kivy
kivy.require('1.10.0')
import widgets_1
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.lang import Builder
Builder.load_string("""
<MyBox>:
MyLabel:
admin: "user"
line_color: "blue"
line_width: 5
""")
class MyBox(MDBoxLayout):
pass
class MainApp(MDApp):
def build(self):
self.screen = MDScreen()
self.box = MyBox()
self.screen.add_widget(self.Box)
return self. Screen
if __name__ == "__main__":
app = MainApp()
app.run()
widgets_1.py:
import kivy
kivy.require('1.10.0')
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivymd.uix.boxlayout import MDBoxLayout
class MyLabel(MDBoxLayout):
admin = StringProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
print("admin", self.admin)
if self.admin == "user":
self.md_bg_color = "green"
else:
self.md_bg_color = "red"
Thanks!
You can use an on_admin() method to execute some code whenever the admin property changes. Try redefining your MyLabel class as :
class MyLabel(MDBoxLayout):
admin = StringProperty()
def on_admin(self, instance, new_value):
print("admin", self.admin)
if self.admin == "user":
self.md_bg_color = (0,1,0,1)
else:
self.md_bg_color = (1,0,0,1)
or, another approach is to just put the logic in the kv:
<MyBox>:
MyLabel:
admin: "user"
line_color: "blue"
line_width: 5
md_bg_color: (0,1,0,1) if self.admin == 'user' else (1,0,0,1)
and then the on_admin() method is not needed.

My kivy code is not displaying anything. Please tell me where I am going wrong

i have designed a kivy form which takes some information from the user..But none of it is getting displayed..Please tell me where I am going wrong.
My code:
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.floatlayout import FloatLayout
class Widgets(Widget):
pass
class YourDiaryApp(App):
def build(self):
return Widgets()
if __name__ == "__main__":
YourDiaryApp().run()
Kivy code:
<Widgets>:
FloatLayout:
Label:
text:'What do you want me to call you'
TextInput:
id:username
Label:
text:'What do you wanna call me'
TextInput:
id:diaryname
Label:
text:'What will be your password'
TextInput:
id:password
Button:
text:'Complete Setup'
Is your KV file named "yourDiaryApp.kv"? From the docs:
There are two ways to load Kv code into your application:
By name convention:
Kivy looks for a Kv file with the same name as your App class in lowercase, minus “App” if it ends with ‘App’ e.g:
MyApp -> my.kv
My guess would be the KV code isn't being loaded.

how to reference kivy widget ids dynamically created using kv language through a for loop in main python file?

I have dynamically created textinput widgets in a .kv file using kv language. However i would like to set the text in main python file using a for loop by referencing their ids.
I have written the following code:
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
class setText(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
texts=['txtip1','txtip2']
IDS=self.ids.keys()
for i in range(IDS):
self.ids[IDS[i]].text=texts[i]
class DocApp(App):
def build(self):
return Builder.load_file("docapp\Doc.kv")
return setText()
if __name__=="__main__":
DocApp().run()
Doc.kv
# File: docapp.py
#: import TextInput kivy.uix.textinput.TextInput
GridLayout:
cols:1
on_kv_post:
[self.add_widget(TextInput(id=str(i))) for i in range(2)]
I have searched through other questions but couldn't find suitable solution. Please help
The problem in your code, is that id only works in the kv syntax.
So you need to reference your widgets some other way.
In case you need to do it that way, dynamically adding in kv and accessing in a loop in python, you could try something like the example below.
The text will change after 5 seconds in this case. If you know that the only children of this gridlayout will be the widgets you want to access, you might as well just iterate the children.
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
KV = """
#: import TextInput kivy.uix.textinput.TextInput
GridLayout:
cols:1
on_kv_post:
for i in range(2): app.dynamic_widgets.append(TextInput())
for wid in app.dynamic_widgets: self.add_widget(wid)
"""
class DocApp(App):
dynamic_widgets = []
def build(self):
Clock.schedule_once(self.set_text, 5)
return Builder.load_string(KV)
def set_text(self, dt):
texts=['txtip1','txtip2']
for text, wid in zip(texts, self.dynamic_widgets):
wid.text = text
if __name__=="__main__":
DocApp().run()
Now if you remove one of the widgets, you probably want to remove it from the list also.
You can create the TextInput widgets dynamically in kv by creating the kv dynamically. Here is a modification of your code that does that:
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
class DocApp(App):
def build(self):
# schedule the call to add the texts
Clock.schedule_once(self.setText)
# return the root widget from the kvString
return layoutRoot
def setText(self, dt):
texts=['txtip1','txtip2']
IDS=self.root.ids.keys()
i = 0
for id in IDS:
self.root.ids[id].text=texts[i]
i += 1
if __name__=="__main__":
# Create the kv string here
kvString = '''
GridLayout:
cols:1
'''
for i in range(2):
kvString += ' TextInput:\n' + ' id: ' + str(i) + '\n'
# Load the kv string
layoutRoot = Builder.load_string(kvString)
# and finally, run the App
DocApp().run()
I have eliminated the setText class (assuming it was only a holder for the setText method), and placed that method in the App. The Clock.schedule_once() schedules the call to setText to happen after the App has been created.

How to implement for loop in .kv file

I have written a python code in python file(main.py) to create a kivy app that contains dynamically created labels which works fine.
Here is main.py file
main.py
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
class createLabels(GridLayout):
def __init__(self,**kwargs):
super().__init__(**kwargs)
self.cols=1
labels=[Label(text='Label '+str(i)) for i in range(5)]
[self.add_widget(label) for label in labels]
class DocApp(App):
def build(self):
return createLabels()
if __name__=="__main__":
DocApp().run()
However i would like to dynamically create labels similar to the one above using a kivy language file (.kv). I am not sure whether we can use lists and for statements in .kv file. I tried the solution mentioned in one of the similar type question but it didn't work.
You could use on_kv_post which runs when the kv class which you use on_kv_post is ready. And dynamically, like in push of buttons, is basically the same as in the example below.
from kivy.app import App
from kivy.lang import Builder
KV = '''
#: import Label kivy.uix.label.Label
GridLayout:
cols: 1
on_kv_post:
[self.add_widget(Label(text="Label " + str(i))) for i in range(9)]
'''
class TestApp(App):
def build(self):
return Builder.load_string(KV)
if __name__ == '__main__':
TestApp().run()

Resources