I always see people creating big structures in .kv files. Sometimes they write the kv in a variable in the .py file.
Here I'm trying to create a widget with kv language in .py file but it doesn't work.
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivymd.uix.textfield import MDTextFieldRect
class App(MDApp):
def build(self):
print("building app")
self.screen = Screen()
return self.screen
def on_start(self):
print("starting app")
kv = '''
MDTextFieldRect:
'''
e = Builder.load_string(kv)
self.screen.add_widget(e)
if __name__ == "__main__":
app = App()
app.run()
And I know that I can do it another way but I want to learn how to do it like this because I have troubles creating some widget with python when it works in kv language.
Here is a working example of how I could do it but I need to learn another way.
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivymd.uix.textfield import MDTextFieldRect
class App(MDApp):
def build(self):
print("building app")
self.screen = Screen()
return self.screen
def on_start(self):
print("starting app")
self.screen.add_widget(MDTextFieldRect())
if __name__ == "__main__":
app = App()
app.run()
Related
This code compile correctly.
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.textfield import MDTextFieldRect
from kivy.lang import Builder
class App(MDApp):
def build(self):
self.screen = Screen()
return self.screen
def on_start(self):
l = BoxLayout()
self.screen.add_widget(l)
w = MDTextFieldRect()
l.add_widget(w)
App().run()
But If you just change the widget from MDTextFieldRect to MDTextFieldRound or MDTextField, the application will crash and I don't know why (there is no apparent error message).
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.textfield import MDTextFieldRound
from kivy.lang import Builder
class App(MDApp):
def build(self):
self.screen = Screen()
return self.screen
def on_start(self):
l = BoxLayout()
self.screen.add_widget(l)
w = MDTextFieldRound()
l.add_widget(w)
App().run()
And to confuse me even more, it can work if you use the kv langage !!!
from kivymd.app import MDApp
from kivy.lang import Builder
KV = '''
Screen:
MDTextFieldRound:
icon_left: 'key-variant'
normal_color: app.theme_cls.accent_color
'''
class App(MDApp):
def build(self):
self.screen = Builder.load_string(KV)
return self.screen
App().run()
I have a custom button. I cannot put it on screen via kv file. I studied a lot topics. No useful info can find. Here is a simple example:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<MyGrid>:
Button
text: 'hello'
''')
class MyGrid(BoxLayout):
pass
class DropApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
DropApp().run()
Note that the Button in this kv file is native Kivy button. I run this code, I can see this button on screen. But now I have a custom Button:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
#:kivy 1.11.0
<MyGrid>:
customButton:
''')
class MyGrid(BoxLayout):
pass
class customButton(Button):
def __init__(self, **kwargs):
self.text = 'hi'
super(Button, self).__init__(**kwargs)
class DropApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
DropApp().run()
I run this code, I cannot see this customButton on screen. Note that the custom widget is complex. I have to define it in py file. For example:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
class DropApp(App):
def build(self):
layout = GridLayout(cols=1, spacing=10)
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
return layout
if __name__ == '__main__':
DropApp().run()
Building this layout need for loop. I cannot find a way to build it in kv file. So I define it in Py file. But if I define it in py file, I cannot work with it in kv file.
Question 1: What's wrong with the second code?
Question 2: If I can't make it work, can I achieve the third code in kvlang(in kv file not in python)?
I am new to Kivy, hope someone can help.
When I run the code on Kivy v1.11.1 , Python v3.7.5:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
class DropApp(App):
def build(self):
layout = GridLayout(cols=1, spacing=10)
for i in range(100):
btn = Button(text=str(i), size_hint_y=None, height=40)
layout.add_widget(btn)
return layout
if __name__ == '__main__':
DropApp().run()
The output is:
If this is the output you require, try running:
pip install --upgrade kivy
For the second code, python is case-sensitive. So instead of customButton, use CustomButton.
If you want to do the 3rd code using .kv file, here is an example:
from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.lang import Builder
Builder.load_string('''
<ExampleRV>:
viewclass: 'Button'
RecycleBoxLayout:
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
''')
class ExampleRV(RecycleView):
def __init__(self, **kwargs):
super(ExampleRV, self).__init__(**kwargs)
self.data = [{'text': str(x)} for x in range(20)]
class RecycleApp(App):
def build(self):
return ExampleRV()
RecycleApp().run()
For reference, go HERE.
I'm runing "Kivy" on Windows 10. When I use "Images" in Kivy App... it returns Blank screen..
My code is Following(Code files and Images are in same folder)
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.image import Image
class Game(Widget):
def __init__(self):
super(Game, self).__init__()
self.background = Image(source='backGround.jpg')
self.size = self.background.size
self.add_widget(self.background)
self.add_widget(Image(source='bird.jpg'))
class GameApp(App):
def build(self):
return Game()
if __name__ == "__main__":
GameApp().run()
Please Someone point out Mistake... I'll be greatful... Regards
I need to access the height of a widget after it is created. However, whenever I tried to access my_widget.height, it returns the default height of 100 rather than the actual height.
Retrieving self.height inside the on_touch_down definition of the my_widget class works though.
My problem is really best described in the following code.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class Layout(BoxLayout):
# the following yields the correct height of Layout,
# which is the same as the height of the Window
def on_touch_down(self, touch):
print("inside Layout via on_touch_down:", self.height)
class MyApp(App):
def build(self):
l = Layout()
# However, accessing the height here yields the
# the default height 100
print("inside MyApp:", l.height)
return l
if __name__ == "__main__":
MyApp().run()
I spent hours reading different parts of the API doc and the guides on the Kivy website, but couldn't quite find what I missed.
In the build() method the application has not yet been built so the widget has its default value, so you must obtain that information a moment later, for this there are the following options:
Use App.on_start():
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class Layout(BoxLayout):
pass
class MyApp(App):
def build(self):
l = Layout()
return l
def on_start(self):
print(self.root.height)
if __name__ == "__main__":
MyApp().run()
Use Clock.schedule_once():
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
class Layout(BoxLayout):
pass
class MyApp(App):
def build(self):
l = Layout()
Clock.schedule_once(self.after_build)
return l
def after_build(self, dt):
print(self.root.height)
if __name__ == "__main__":
MyApp().run()
I don't have any idea to find a solution of my problem.
I have make an application with Carousel Widget. In this Carousel I have 4 slides.
welcomeSlide -> DVDSlide -> DVDPretSlide --> CategorySlide
I have make a class for each slides.
I use a ListAdpter to display the data extracted from an Sqlite3 Database.
My pblem is about the refresh of the list, when I modify a DVD (add name to pret) in the DVDSlide, when I slide to the DVDPret, the DVD do not appears because the List is not refresh.
Like the doccumentation for the carousel I don't find the event when slide change. It will be the best if an event exist to get the current slide index.
Have you got any Idea ?
Thanks,
You can observe index property:
from kivy.uix.carousel import Carousel
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
Label:
text: str(id(root))
<Carousel>
on_index: print("slide #{}".format(args[1]))
''')
class Page(BoxLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()
Or you can observe current_slide property:
from kivy.uix.carousel import Carousel
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
label_id: label_id
Label:
id: label_id
text: str(id(root))
<Carousel>
on_current_slide: print(args[1].label_id.text)
''')
class Page(BoxLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()
If you want a pure python solution rather than a Kivy Language solution you can create your own carousel that inherits from the Kivy carousel as follows.
import kivy
from kivy.uix.carousel import Carousel
class MyCarousel(Carousel):
# This class is a carousel that runs script
# when a slide gets focus (except first load).
def on_index(self, *args):
print('the slide is', self.index)
# YOUR CODE GOES HERE
Carousel.on_index(self, *args)