Reputation: 17193
My simplified .kv
file:
<GameWorld>:
player: the_player
canvas:
Rectangle:
pos: 5, root.top - 25
size: self.player.health, 20 # error raised in this line
Player:
id: the_player
center: self.center
My simplified Python file:
class Player(Widget):
health = NumericProperty(50)
def __init__(self, **kwargs):
super(Player, self).__init__(**kwargs)
self.health = 100
class GameWorld(Widget):
player = ObjectProperty()
entities = ListProperty()
def __init__(self, **kwargs):
super(GameWorld, self).__init__(**kwargs)
self.entities.append(self.player)
The error I get:
AttributeError: 'NoneType' object has no attribute 'health'
Kivy thinks self.player
is None
. Please help me understand what's wrong.
Upvotes: 2
Views: 607
Reputation: 5157
When the canvas
instructions are evaluated, GameWorld.player
is still None
, the default for ObjectProperty
, hence the error.
If you add a test for None
to the kv rule like this:
<GameWorld>:
player: the_player
canvas:
Rectangle:
pos: 5, root.top - 25
size: self.player is not None and self.player.health, 20
No error will be thrown, but automatic binding will not be performed. However, if you add rebind=True
to the declaration of the ObjectProperty
:
class GameWorld(Widget):
player = ObjectProperty(rebind=True)
this will work correctly.
Leaving less elegant alternate solutions up:
You could instantiate a Player
object at definition:
class GameWorld(Widget):
player = ObjectProperty(Player())
Or, you could add another NumericProperty
to GameWorld
, with the sole purpose of being bound to player.health
, but initialized to a sensible value:
class GameWorld(Widget):
_player_health = NumericProperty(1)
and
<GameWorld>:
player: the_player
_player_health: the_player.health
canvas:
Rectangle:
pos: 5, root.top - 25
size: self._player_health, 20
Upvotes: 1