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

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

Related

Kivy keeps coming up blank

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.

Using a button to load a kv file

Hi all my question is a basic one. I'm using a .kv file in which I have defined a button that changes screens. I would like to use that button to load .kv file. I can use builder.load(kv2.kv) ?
I've tried a bunch of different ways writing it out. The stats.kv file loads all my RPG stats. If I remove the builder statement, I just get the next screen. All my widgets are in a different .kv files for ease of debugging purposes. I just need to load multiple .kv files within a .kv file.
However this error always occurs:
AttributeError: 'RevengeApp' object has no attribute 'builder'
Button in .kv file:
Button:
text: "Confirm"
on_press: app.builder.load(stats.kv)
on_release: app.root.current = "AStats"
Did you assign the Builder object to the builder attribute of your app? because that's what your kv code seems to expect.
from kivy.lang import Builder
[…]
class RevengeApp(App):
def build(self):
self.builder = Builder
should do it.
But you could also just import Builder directly in your kv code by doing
#:import builder kivy.lang.Builder
at the top of your kv file, and then replace your app.builder.load with builder.load_file in your on_press binding.

python code won't run with .kv file

I have my python code:
from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
class Premade(BoxLayout):pass
class MyFirstApp(App):
def build(self):
return Premade()
if __name__ == '__main__':
MyFirstApp().run()
and my .kv file:
#:kivy 1.10.0
<Premade>:
orientation: 'Verticle'
TextInput:
id: my_textinput
font_size: 150
size_hint_y: None
height: 200
text: 'default'
FloatLayout:
Scatter:
Label:
text: my_textinput.text
font_size: 150
Supposedly, when I run the python code, the .kv file would be loaded, but all I get is a black screen. I named my .kv file according to the rule, in this case, is myfirst.kv and the .kv file is also in the same directory as the python module file. I also tried to use the build function but that didn't work either. Can anyone help?
Check your .kv filename, if you want it to be loaded automatically you should name it MyFirst.kv because your app is called MyFirstApp. An alternative solution would be to load the file manually as the following:
from kivy.lang import Builder
Builder.load_file('filename.kv')
Has to be called myfirstapp.kv or the same name as the app class

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']

Why is this code is making two copies of the widgets?

This makes two tabs for each TabbedPanelItem plus the default tab. Why does this happen and how do I prevent it?
Kivy:
:
TabbedPanelItem:
text: 'List'
TabbedPanelItem:
text: 'Add/Edit'
TabbedPanelItem:
text: 'Delete'
Python:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.tabbedpanel import TabbedPanel
presentation = Builder.load_file('my.kv')
class Panel(TabbedPanel):
pass
class MyApp(App):
def build(self):
return Panel()
if __name__ == '__main__':
MyApp().run()
Your kv file is being loaded twice, once by your explicit Builder.load_file and once implicitly because it has the same name as your App class (but lowercase and without the App, as expected for the default kv file to be loaded).
Remove the explicit Builder.load_file and it should work.

Categories

Resources