I'm trying to create a simple application using Kivy where an image fills up the entire widget. I wrote code for this using a kv file and it worked just fine. But, if I try to make it entirely in the python file, it doesn't work and self.size
gives the value (100, 100)
, which results in a 100 x 100 image on the bottom left corner of the window.
Here's my code for the kv file approach :
from kivy.app import App
from kivy.uix.widget import Widget
class MainWidget(Widget):
pass
class MainApp(App):
def build(self):
return MainWidget()
MainApp().run()
kv file :
<MainWidget>:
canvas.before:
Rectangle:
source: "background.jpg"
size: self.size
Here's my attempt at making it entirely in the python file :
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import *
class MainWidget(Widget):
def __init__(self, **kwargs):
super(MainWidget, self).__init__(**kwargs)
with self.canvas.before:
Rectangle(size = self.size, source = "background.jpg")
class MainApp(App):
def build(self):
return MainWidget()
MainApp().run()
Aren't the two approaches equivalent? What's causing the unexpected output?
The two methods that you show are not equivalent. One of the major advantages of using kv
is that it automatically sets up bindings for you. So the kv
code:
size: self.size
sets up a binding so that whenever the size
of the MainWidget
changes, the size
of the Recrangle
will be adjusted to the same.
In the code where you do not use kv
no such binding is created. In that code the size
of the Rectangle
is set when the code:
Rectangle(size = self.size, source = "background.jpg")
is executed. At that point, the size
of MainWidget
is still the default of (100 100)
and the position is the default of (0, 0)
. If you want the size
of the Rectangle
to be updated, you must provide the code to do so. Here is an example of one way to do that:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import *
class MainWidget(Widget):
def __init__(self, **kwargs):
super(MainWidget, self).__init__(**kwargs)
with self.canvas.before:
self.rect = Rectangle(size = self.size, source = "background.jpg")
def on_size(self, *args):
self.rect.size = self.size
class MainApp(App):
def build(self):
return MainWidget()
MainApp().run()