Kivy keeps coming up blank - python

I am trying to learn kivy and have two files open my main python file and a kv file for styling, everytime I run the python file the resulting window always comes up blank. I am running it using python main.py on windows 10.
main.py
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.label import Label
class CustomLabel(Label):
pass
class App(App):
def build(self):
return CustomLabel()
app = App()
app.run()
kivy.kv
<CustomLab#Label>:
font_size: 32
<CustomLabel>:
CustomLab:
text: "Hello World"

I wanted to edit your post and comment but I can't.
You should not name your main class as "App" instead you can name it like "TestApp".
Like this:
class TestApp(App):
Also your kivy file's name should be a lowercase of your "TestApp" without the word "App" on it.
Like this:
test.kv
Inside your kivy file, you misspelled the class "CustomLabel" as "CustomLab".
To declare a class inside a kivy file, you must use a "<" and ">".
Like this:
<CustomLabel>:
I changed your code and it looked like this:
This is your main.py:
import kivy
kivy.require("1.9.0")
from kivy.app import App
from kivy.uix.label import Label
class CustomLabel(Label):
pass
class TestApp(App):
def build(self):
return CustomLabel()
app = TestApp()
app.run()
This is your test.kv:
<CustomLabel>:
text: "Hello World"
font_size: 32
I hope this will work.

Related

Kivy showing a black screen when trying to use kv file?

So I want to do the styling of my Kivy app in a external .kv file, but when I run the main code, nothing appears to the black Kivy window.
Here's my main file called main.py
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
class MyGrid(Widget):
pass
class MyApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
MyApp().run()
And here's the .kv file located in the same directory and called my.kv
#:kivy 2.0.0
<MyGrid>:
Label:
text: "example example"
So I'm not getting any error, just nothing appearing in the Kivy GUI when I run the main code.
Why is this and how to fix it?
In order to load widgets from a separate kivy file, you need to import Builder:
from kivy.lang.builder import Builder
Builder.load_file('my.kv')
or in .py file
Builder.load_string("""
<MyGrid>:
Label:
text: "example example"
""")
The kivy file name should always be the App class name, in your case you should save file with MyApp.kv
else you need to use Builder to import

Having difficulty in loading .kv file

I've saved both my python and kv file in the same folder but the program is unable to load it implicitly using the app name. I've tried using Builder.load_file() to load it explicitly but it results in a file not found error.
The only way it works is if i use the Builder.load_string() function but it makes the code tough to manage and also very badly organized. I'd really appreciate some help fixing this error.
maybe you can check whether your app class name match your .kv file
e.g.
.py
class MyKivyApp(App): # <-- here you should name your .kv file as mykivy , it comes from the class name "MyKivyApp" without the "App"
def build(self):
...
so the .kv file name will be mykivy.kv
or you can try kivy.lang.Builder.load_string() in .py , it just like the .kv but in the form of string ...
e.g.
.py
import kivy
from kivy.uix.widget import Widget
kivy.lang.Builder.load_string(
'''
#:kivy 2.0.0
<MyApp>
Button:
text: 'Helo World !"
size: root.size
''')
class MyApp(Widget):
pass
class mykivyApp(App):
def build(self):
main = MyApp()
return main
sth like this

How to bring a variable from the .py file to the .kv file?

Kv language has a way to import names from other files using the following syntax:
#:import name x.y.z
# The same as `from x.y import z as name` in Python code
But it doesn't mention how to import the values from the same module where that kv language is used.
Let's say I have the following code:
from kivy.app import App
from kivy.lang import Builder
from kivy.atlas import Atlas
from kivy.uix.button import Button
theme = Atlas('path/to/atlas')
Builder.load_string('''
<MyWidget>:
background_normal: theme['widget_bg']
''')
class MyWidget(Button):
pass
class TestApp(App):
def build(self):
return MyWidget()
TestApp().run()
I'd like to import the theme Atlas object into the kv code to set the proper background. How could this be done?
You can refer to your current module as __main__
#:import theme __main__.theme
<MyWidget>:
background_normal: theme['widget_bg']

Understanding Kivy properities and binding methods

I am having problems understanding the usage of custom Properities and ways of binding methods to events.
Here's my code:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import StringProperty
kivy_lang = '''
<MainWidget>:
on_my_property: my_label.text = 'from button bind method via StringProperty' + my_property
Label:
id: my_label
text: root.my_property
Button:
id: my_button
text: 'intro button'
'''
class MainWidget(BoxLayout):
# bind some properties
my_property = StringProperty('0')
def __init__(self, **kwargs):
super(MainWidget, self).__init__(**kwargs)
# if needed to do sth on widget construction
self.ids.my_button.bind(on_press=self.my_method)
def my_method(self,*args,**kwargs):
self.my_property = str(int(self.my_property)+1)
self.ids.my_button.text = 'new'
class MyApp(App):
def build(self):
Builder.load_string(kivy_lang)
return MainWidget()
if __name__ == '__main__':
MyApp().run()
When I run it it renders OK, but when I click a button, as a result I get
NameError: name 'my_property' is not defined
I tried binding method for Button in kv lang with (and removing whole 'init()' on python side):
on_press: root.my_method
and then when I press button the app doesn't crash but nothing happens
Can someone explain me how to adjust this code to work?
I understand the code is a little 'mixed techniques' but I did it that way to get to know different approaches, so I would appreciate if You don't turn it all around :)
1/ you are missing 'self' before 'my_property' in 'on_my_property' bindind, hence the crash
2/ in kv bindings. the python code is called as written, so you need '()' after 'root.my_method', or the statement has no effect.

How do I set widget attributes by calling a function in Kivy Python?

Suppose I have a ThemeManager object as a class attribute in my RootWidget like so:
class RootWidget(Widget):
theme = ThemeManager()
The ThemeManager defines a function that returns a hex color.
class ThemeManager:
def get_color(self):
return '#ffffffff'
Let's say I create a Button in my RootWidget using a kv file. How would I be able to call the ThemeManager functions from the kv file? Here's an example that doesn't work:
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.lang import Builder
class ThemeManager:
def get_color(self):
return '#ffffffff'
class RootWidget(Widget):
theme = ThemeManager()
my_kv = Builder.load_string("""
#: import get_color_from_hex kivy.utils.get_color_from_hex
RootWidget:
Button:
color: get_color_from_hex(app.root.theme.get_color())
text: "Test"
""")
class TestApp(App):
def build(self):
return my_kv
if __name__ == '__main__':
TestApp().run()
Since your question is already answered, here's a stab at the explanation, it's actually pretty simple (I think).
app.root is None at the point where your Button is trying to read the function. Because the order of things is (loosely):-
RootWidget created
Once it and all it's children are done (init completed), the object gets passed to the line in build()
app.root is only set on the call to TestApp.run()
As to why 3. happens, the init method in app.py initializes self.root as None. It can then be set by load_kv (loads a kv with the same name as this app) or by run (which is what happens most of the time).
So you can call app.root in your on_press events (because these only happen in response to user interaction, when the app is fully created) but not in one-off widget initialization events.
Interestingly enough, root is not defined as an ObjectProperty in app.py, which means you can't bind to changes in it like you can with, say, the title and icon. Not sure if it'd ever change though, so this is probably moot.

Categories

Resources