How can I pass object properties to the Kivy .kv file

1.4k Views Asked by At

My queston is related to Python / Kivy. I'm in need to use various textures for game blocks (i.e. square fields, 40 x 40) depending on their types. I tried the most natural way to me, i.e. define the type as an object attribute, and test the value in the .kv file. Alas, the attribute is not recognized. I'm pretty sure this is something simple, and resulting from my misunderstanding of some concept. Stil I can't make it out from the available docs. Thanks in advance for putting me in the right direction.

Consider the following example code. It's quite a big chunk, but this is the cost of it being complete to run.

# Imports
from os import system as _system

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.vector import Vector
from kivy.config import Config
from kivy.uix.image import Image

# Size of the map in memory
MAXX = 1001
MAXY = 150

# Size of the display, counted in blocks
MAXSCREENX = 91
MAXSCREENY = 60

# Single block size
BLOCK_SIZE = 40

# Global data structures
game_state = []
mapa = []
player_position = []
equipment = []
eye_direction = 0

# Various subclasees, because of different GIFs defined in the .ky file
class Block(Widget):
    typ = NumericProperty(0)

class GameWidget(Widget):
    xshift = NumericProperty(0)
    yshift = NumericProperty(0)

class ExampleApp(App):
    def build(self):
        game = GameWidget()
        game.xshift = 0
        game.yshift = 0
        game.screen_map = []
        for i in range(MAXSCREENX):
            for j in range(MAXSCREENY):
                idx = i*MAXSCREENY + j
                game.add_widget(Block(), idx)
                game.children[idx].pos = (i * BLOCK_SIZE, j * BLOCK_SIZE)
                game.children[idx].typ = 2
        return game

if __name__ == '__main__':
    # Set the window size
    Config.set('graphics', 'width', str(MAXSCREENX * BLOCK_SIZE))
    Config.set('graphics', 'height', str(MAXSCREENY * BLOCK_SIZE))

    ExampleApp().run() # Launch the main application     

with the accompanying example.kv file:

#:kivy 1.9.0

<Block>:
    size: 40, 40
    canvas:
        Rectangle:
            if self.typ == 2:
                source: "Textures/Dirt.png"
            pos: self.pos
            size: 40, 40

Alas, I get the following error:

kivy.lang.ParserException: Parser: File "C:\Moje\Example\example.kv", line 7:
...
       5:    canvas:
       6:        Rectangle:
 >>    7:            if self.typ == 2:
       8:                source: "Textures/Dirt.png"
       9:            pos: self.pos
1

There are 1 best solutions below

3
On

You are improperly using Python expressions in kv language. See the docs for proper syntax. Specifically, you need to move your if expression after source:

Rectangle:
    source: "Textures/Dirt.png" if root.typ == 2
    pos: self.pos
    size: 40, 40