I am trying to use Kivy to create an interface. But when I try to show the text of a variable (result) it doesn't show it. Here the code:
from kivymd.app import MDApp
from kivy.lang import Builder
from covid import Covid
covid = Covid(source='worldometers')
data = covid.get_status_by_country_name('Italy')
for k in data:
result = k+str(data[k])
KV = '''
Screen:
Label:
text: result
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
'''
class MainApp(MDApp):
def build(self):
self.title = "Covid"
self.theme_cls.theme_style = "Dark" # Light
self.theme_cls.primary_palette = "Red"
return Builder.load_string(KV)
MainApp().run()
I'm sorry for my english but I'm Italian then I'm not very good.
Good day. Kivy is an App framework. You need to create an entire App class and build your logic into the App.
I recommend that after you create the App class, instantiate it, run it, then run your logic code in your App.
kv script:
Screen:
MDRectangleButton:
on_release: app.calculate_result_callback
In Python:
import .......
data = covid.get_status_by_country_name('Italy')
covid = Covid(source='worldometers')
def calculate_result():
result = ""
for k in data:
result += k+str(data[k])
return result
class MyApp(App):
def calculate_result_callback(self, instance, *a):
result = calculate_result()
instance.text = result
Related
I have this code below. I've set id by python code, but I couldn't access.
def abrirReceita(self,instance):
instance.text = str(instance.ids)
I'd like to change the text with the number of the ID when I press.
Exemple: if I input the first button, change the text for '1', which is the ID I've passed.
from kivymd.app import MDApp
from kivymd.uix.boxlayout import BoxLayout
from kivymd.uix.floatlayout import FloatLayout
from kivymd.uix.list import TwoLineListItem
from kivymd.uix.textfield import MDTextField
from kivy.lang import Builder
import os
from kivy.core.window import Window
import sqlite3
KV = '''
ScreenManager:
Screen:
name: 'telaSelecionada'
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: tb
title: 'Drinks'
md_bg_color: 0, 0, 0, 1
TelaSelecionada:
id: telaselecionada
<TelaSelecionada>:
ScrollView:
MDList:
id: mostraReceita
padding: '20dp'
'''
Window.softinput_mode = "below_target"
class TelaSelecionada(FloatLayout):
pass
class Aplicativo(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
i = 1
for x in range(5):
self.textLine = TwoLineListItem(text = 'change text', secondary_text = 'change text')
self.root.ids.telaselecionada.ids.mostraReceita.add_widget(self.textLine)
self.root.ids.telaselecionada.ids.mostraReceita.ids[i] = self.textLine
self.textLine.bind(on_release = self.abrirReceita)
i += 1
def abrirReceita(self,instance):
instance.text = str(instance.ids)
Aplicativo().run()
How do I access the IDs from python code?
I'd like to change the text with the number of the ID when I press.
Just pass the required args through method abrirReceita using functools.partial as,
def on_start(self):
...
self.textLine.bind(on_release = partial(self.abrirReceita, i))
i += 1
# Then in `abrirReceita` :
def abrirReceita(self, id_index, instance):
instance.text = str(id_index)
Note:
The ids are not used here at all (actually you don't need that here for this purpose) !
Update:
As, the Widget.id has been deprecated since version 2.0.0 you should use it only in kvlang not in python.
But that doesn't keep you from creating it as a dynamically added attribute. Thus you can do something like this (I modified the on_start method a little):
def on_start(self):
mostraReceita = self.root.ids.telaselecionada.ids.mostraReceita
for i, _ in enumerate(range(5), start=1):
# Or just,
# for i in range(1, 5+1):
self.textLine = TwoLineListItem(
text = 'change text',
secondary_text = 'change text',
)
self.textLine.index = i
# Or even,
# self.textLine.id = i
self.textLine.bind(on_release = self.abrirReceita)
mostraReceita.add_widget(self.textLine)
def abrirReceita(self,instance):
instance.text = str(instance.index) # or, str(instance.id)
I am building a German dictionary app where there is an option to get gender of German nouns in Kivy python and I wanted to have an unfocus event in the Text Input so only when the user unfocuses from the
'MDTextFieldRound' , the search method can be called which will give the list of all german nouns according to entered prefix in the MDTextField...
Here is the main python file:
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivymd.uix.textfield import MDTextFieldRound
from mst import genderGetter
from kivymd.uix.list import TwoLineListItem
class MenuScreen(Screen):
pass
class GenderGameScreen(Screen):
pass
class GenderScreen(Screen):
words = list(genderGetter().keys())
def get_len(self):
return len(self.get_text())
def search(self):
self.get_text()
self.create_list()
def get_text(self):
gen = self.ids.gender.text.lower().capitalize()
return gen
def create_list(self):
for word in self.words:
if self.get_text() in word[0:self.get_len()]:
items = TwoLineListItem(text=word, secondary_text=genderGetter().get(word))
self.ids.contain.add_widget(items)
class GenderText(MDTextFieldRound):
pass
class TranslatorScreen(Screen):
pass
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
class GermanApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Blue"
screen = Builder.load_file('kv files/main.kv')
return screen
if __name__ == "__main__":
app = GermanApp()
app.run()
Here is the kivy file of gender.kv
<GenderScreen>:
id:genders
name:'gender'
ScrollView:
size_hint:(.5,.8)
MDList:
id: contain
MDTextFieldRound:
id: gender
hint_text: "Enter the German noun"
helper_text: "Correct one"
helper_text_mode: "on_focus"
pos_hint : {"center_x" : 0.45 , "center_y" : 0.9}
icon_right_color:app.theme_cls.primary_color
size_hint_x : 0.8
on_text:root.search()
I am still a noob in kivy so there can be many potential mistakes in code...
Please consider that..
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanger import ScreenManager, Screen
Builder.load_string("""
<MenuScreen>:
BoxLayout:
FloatLayout:
Image:
id: homebackg
pos: 0, 0
source: "dark.png"
<SettingsScreen>:
BoxLayout:
FloatLayout:
Image:
id: settingsbackg
pos: 0, 0
source: "dark.png"
Button:
text: ""
color: 1.0, 1.0, 1.0, 0.0
on_press:
root.buttonclick()
""")
class MenuScreen(Screen):
def darkmode(self):
self.ids.homebackg.source = "dark.png"
def litemode(self):
self.ids.homebackg.source = "lite.png"
class SettingsScreen(Screen):
def darkmode(self):
self.ids.settingsbackg.source = "dark.png"
def litemode(self):
self.ids.settingsbackg.source = "lite.png"
def buttonclick(self):
file = open("stat.txt", "r")
themestat = file.read()
file.close()
if themestat == "lite":
SettingsScreen.darkmode(self)
MenuScreen.darkmode(self)
file = open("stat.txt", "w")
file.write("dark")
file.close()
elif themestat == "dark":
SettingsScreen.litemode(self)
MenuScreen.litemode(self)
file = open("stat.txt", "w")
file.write("lite")
file.close()
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))
class MyApp(App):
def build(self):
return sm
if __name__ == '__main__':
MyApp().run()
Assume I have done the screen transitions properly not adding to make code less bulky, I have issue with changing background of menuscreen from the settingsscreen. It is for darkmode you see, thanks in advance.
Self is not defined when executing MenuScreen.darkmode(self) from SettingsScreen.
You problem is that you are adding objects of screens to screen manager (and you will see only these objects) and then you are creating new objects and make changes there. So since you are using global variables the simplest solution would be:
sm = ScreenManager()
menuscreen = MenuScreen(name='menu')
settingsscreen = SettingsScreen(name='settings')
sm.add_widget(menuscreen)
sm.add_widget(settingsscreen)
And inside the classes you can just make changes to them like:
menuscreen.darkmode()
P.S. 'self' means object of the class, in Python self is used to have access to class variables and functions from functions defined in that class. And here you don't need to send 'self' to another class because you're sending object of SettingsScreen class to MenuScreen darkmode function and do nothing with it. If you want to send object there should be:
# you send object of SettingsScreen
menuscreen.darkmode(self)
# and receive it as obj for example
def darkmode (self, obj):
...
I created a mobile app. Once a user clicks on 1 element on the list I need the text to go into another text-input
My kv file
#:import main main
#:import ListAdapter kivy.adapters.listadapter.ListAdapter
#:import ListItemButton kivy.uix.listview.ListItemButton
<LocationButton>:
deselected_color:0.4, 1, 1,1
selected_color: 0, 0, 1, 1
size: (100, '48dp')
on_press:root.test()
<ecran1>:
nom_du_produit:le_produit
FloatLayout:
ListView:
id:liste_des_produits
size_hint:.5,.8
pos_hint:{'x':.25,'y':.0}
adapter:
ListAdapter(data=root.L,cls=main.LocationButton)
TextInput:
id:le_produit
text:''
font_size:20
size_hint:.2,.1
pos_hint:{'x':.78,'y':.75}
background_color:1,1,1,1
multiline:False
My python code
import kivy
from kivy.app import App
from kivy.uix.screenmanager import Screen,ScreenManager,WipeTransition
from kivy.properties import ObjectProperty,StringProperty,ListProperty
from kivy.uix.listview import ListItemButton
class ecran1(Screen):
L=ListProperty(['tomate','abricot'])
nom_du_produit = ObjectProperty()
class LocationButton(ListItemButton):
L = ListProperty(['tomate', 'abricot'])
nom_du_produit = ObjectProperty()
def test(self):
selection_1 = self.liste.adapter.selection[0].text
self.nom_du_produit.text = selection_1
class PongApp(App):
def build(self):
return ecran1()
if __name__ == '__main__':
PongApp().run()
I tried few options but always the answer is Attribute error
Picture to better understand:This Picture
There are at least two different ways to accomplish what you want. Here is a modification of your test method that shows both:
def test(self):
#App.get_running_app().root.nom_du_produit.text = self.text # uses the ObjectProperty in the ecran1 class
App.get_running_app().root.ids.le_produit.text = self.text # uses the le_produit id in the TextInput class
I have schedule_interval calling a function that fetches weather data from the web and then parses it into a dict. I have my kv file reading that dict and displaying values in a floatlayout. I know the function is being called because I am having it print to the console also, but it is not updating in the floatlayout window. I thought the values would automatically update from what I have read.
GUI.py
class weather(FloatLayout):
def w(self):
a = parse()
print(a)
return a
class weatherApp(App):
def build(self):
d = weather()
Clock.schedule_interval(d.w, 1)
return d
weather.kv
<Layout>:
DragLabel:
font_size: 600
size_hint: 0.1, 0.1
pos: 415,455
text: str(root.w()['temp0'])
This is just one of the labels. I am very new to Kivy so
if this looks atrocious to you experienced kivy
people, I apologize.
The print(a) part of def w(self): works every second, but the window does not display the new variables.
test.py
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
a = {}
a['num'] = 0
class test(FloatLayout):
def w(self):
a['num'] += 1
print(a['num'])
return a
class testApp(App):
def build(self):
d = test()
Clock.schedule_interval(test.w, 1)
return d
if __name__ == '__main__':
p = testApp()
p.run()
test.kv
#:kivy 1.10.1
<Layout>:
Label:
font_size: 200
size_hint: 0.1, 0.1
pos: 415,455
text: str(root.w()['num'])
It seems that you have several misconceptions:
If you invoke a function in python it does not imply that the .kv will be called. So if you call the w method with Clock.schedule_interval() it does not imply that the calculated value updates the value of the Label text.
When you call a function with Clock.schedule_interval you must use the object not a class. in your case, test is class and instead, d is the object.
When you call a function with Clock.schedule_interval you must use the object not a class. in your case, test is class and instead, d is the object.
*.py
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import DictProperty
class test(FloatLayout):
a = DictProperty({"num": 0})
def w(self, dt):
self.a["num"] += 1
print(self.a["num"])
class testApp(App):
def build(self):
d = test()
Clock.schedule_interval(d.w, 1)
return d
if __name__ == "__main__":
p = testApp()
p.run()
*.kv
#:kivy 1.10.1
<Layout>:
Label:
font_size: 200
size_hint: 0.1, 0.1
pos: 415,455
text: str(root.a["num"])