Reputation: 173
I'm trying to learn Kivy with this tutorial. I've copy pasted the code after "Here is the entire code for this step:" to main.py and main.kv as described. When trying to run, I'm getting:
Traceback (most recent call last):
File "main.py", line 47, in <module>
PongApp().run()
File "/home/kivy/code/kivy/kivy/app.py", line 527, in run
root = self.build()
File "main.py", line 41, in build
game.serve_ball()
File "main.py", line 23, in serve_ball
self.ball.center = self.center
AttributeError: 'NoneType' object has no attribute 'center'
What am I doing wrong?
main.kv:
#:kivy 1.0.9
<PongBall>:
size: 50, 50
canvas:
Ellipse:
pos: self.pos
size: self.size
<PongGame>:
ball: pong_ball
canvas:
Rectangle:
pos: self.center_x-5, 0
size: 10, self.height
Label:
font_size: 70
center_x: root.width / 4
top: root.top - 50
text: "0"
Label:
font_size: 70
center_x: root.width * 3 / 4
top: root.top - 50
text: "0"
PongBall:
id: pong_ball
center: self.parent.center
main.py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty, ReferenceListProperty,\
ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock
from random import randint
class PongBall(Widget):
velocity_x = NumericProperty(0)
velocity_y = NumericProperty(0)
velocity = ReferenceListProperty(velocity_x, velocity_y)
def move(self):
self.pos = Vector(*self.velocity) + self.pos
class PongGame(Widget):
ball = ObjectProperty(None)
def serve_ball(self):
self.ball.center = self.center
self.ball.velocity = Vector(4, 0).rotate(randint(0, 360))
def update(self, dt):
self.ball.move()
#bounce off top and bottom
if (self.ball.y < 0) or (self.ball.top > self.height):
self.ball.velocity_y *= -1
#bounce off left and right
if (self.ball.x < 0) or (self.ball.right > self.width):
self.ball.velocity_x *= -1
class PongApp(App):
def build(self):
game = PongGame()
game.serve_ball()
Clock.schedule_interval(game.update, 1.0 / 60.0)
return game
if __name__ == '__main__':
PongApp().run()
Upvotes: 2
Views: 8914
Reputation: 1082
You have the wrong name for your KV file. It should be "pong.kv". If the name of the KV file matches the name of your app (minus App), then it will be automagically used.
You named your KV file "main.kv" which did not match with your app name "PongApp", so the magic did not happen. You were able to manually load the KV file by using Builder.load_file(). If you look back at the tutorial, you can see it requires you to name the KV file as "pong.kv".
Upvotes: 9
Reputation: 173
I've added
from kivy.lang import Builder
Builder.load_file('main.kv')
to my main.py and it works perfectly. Why "main.kv" was not detected automatically is still a mistery to me.
Upvotes: 1
Reputation: 308520
self.ball
is being initialized with:
ball = ObjectProperty(None)
This gives it a default value of None
. Thus when you try to access self.ball.center
it fails.
The tutorial contains a step that you probably missed:
Don’t forget to hook it up in the kv file, by giving the child widget an id and setting the PongGame’s ball ObjectProperty to that id
Upvotes: 1