为什么我得到`'NoneType'对象在.kv文件中没有属性`?

时间:2016-04-28 02:15:33

标签: python kivy

我简化的.kv文件:

<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

我简化的Python文件:

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)

我得到的错误:

AttributeError: 'NoneType' object has no attribute 'health'

Kivy认为self.playerNone。请帮我理解什么是错的。

1 个答案:

答案 0 :(得分:1)

评估canvas说明时,GameWorld.player仍为NoneObjectProperty的默认值,因此错误。

如果您将None的测试添加到kv规则中,请执行以下操作:

<GameWorld>:
    player: the_player
    canvas:
        Rectangle:
            pos: 5, root.top - 25
            size: self.player is not None and self.player.health, 20

不会抛出任何错误,但不会执行自动绑定。但是,如果您将rebind=True添加到ObjectProperty

的声明中
class GameWorld(Widget):
    player = ObjectProperty(rebind=True)

这将正常工作。

提出不那么优雅的替代解决方案:

您可以在定义中实例化Player对象:

class GameWorld(Widget):
    player = ObjectProperty(Player())

或者,您可以向NumericProperty添加另一个GameWorld,其唯一目的是绑定到player.health,但初始化为明智的值:

class GameWorld(Widget):
    _player_health = NumericProperty(1)

<GameWorld>:
    player: the_player
    _player_health: the_player.health

    canvas:
        Rectangle:
            pos: 5, root.top - 25
            size: self._player_health, 20