Kivy AttributeError: 'super' object has no attribute '__getattr__' error

Kivy AttributeError: 'super' object has no attribute '__getattr__' error

我正在尝试在 kivy 中制作游戏,但我遇到了一个问题。每当我点击“开始游戏” 我的游戏屏幕上的按钮显示

line 46, in move_ball
     ball = self.root.ids.ball
   File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__' 

我的main.py

from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.image import Image
from kivy.core.audio import SoundLoader
from kivy.clock import Clock
from kivy.properties import NumericProperty

class HomeScreen(Screen):
    pass

    def play_sound(self):
        sound = SoundLoader.load('button press sound.wav.')
        if sound:
            sound.play()


    sound = SoundLoader.load('Crowd sound effect.wav')
    sound.loop = True
    sound.play()

class GameScreen(Screen):
    pass


class Ball(Image):
    velocity = NumericProperty(0)

    def on_touch_down(self, touch):
        self.source = "icons/ball1.png"
        self.velocity = 275
        super().on_touch_down(touch)

    def on_touch_up(self, touch):
        self.source = "icons/ball1.png"
        super().on_touch_up(touch)

class MainApp(App):
    GRAVITY = 300


    def move_ball(self, time_passed):
        ball = self.root.ids.ball
        ball.y = ball.y + ball.velocity * time_passed
        ball.velocity = ball.velocity - self.GRAVITY * time_passed


    def start_game(self):
        Clock.schedule_interval(self.move_ball, 1/60.)


    def change_screen(self, screen_name):
        # Get the screen manager from the kv file
        screen_manager = self.root.ids['screen_manager']
        screen_manager.current = screen_name


MainApp().run()

homescreen.kv

#:import utils kivy.utils
#:import FadeTransition kivy.uix.screenmanager.FadeTransition


<HomeScreen>:
FloatLayout:
    canvas:
        Color:
            rgb: utils.get_color_from_hex("#39B3F2")
        Rectangle:
            size: self.size
            pos: self.pos
    GridLayout:
        rows: 1
        pos_hint: {"top": 1, "left": 1}
        size_hint: 1, .9
        Image:
            source: "icons/keepyup.png"
    FloatLayout:
        Button:
            font_size: dp(20)
            font_name: 'SackersGothicStd-Medium.otf'
            text: "PLAY"
            color: "gold"
            pos_hint: { "center_x": .5, "center_y": .3}
            size: 80, 55
            size_hint: None, None
            background_normal: ''
            background_color: (57/255.0, 179/255.0, 242/255.0, .15)


            on_press:

            on_release:
                root.play_sound()
                root.manager.transition = FadeTransition()
                app.change_screen("game_screen")

gamescreen.kv

#:import utils kivy.utils


<GameScreen>:
FloatLayout:
    canvas:
        Color:
            rgb: utils.get_color_from_hex("#39B3F2")
        Rectangle:
            size: self.size
            pos: self.pos
    GridLayout:
        rows: 1
        pos_hint: {"top": 1, "left": 1}
        size_hint: 1, .1
        Image:
            source: "icons/sun.png"
    GridLayout:
        rows: 1
        pos_hint: {"top": 1, "left": 1}
        size_hint: 1, .2
        Image:
            source: "icons/clouds.png"
    GridLayout:
        rows: 1
        pos_hint: {"bottom": 1, "left": 1}
        size_hint: 1, .5
        Image:
            source: "icons/Field4.png"
            allow_stretch: True
            keep_ratio: False
            pos: self.pos

    Button:
        text: "Start game"
        size_hint: None, None
        on_release:
            app.start_game()

    Ball:
        source: "icons/ball1.png"
        size_hint: None, None
        size: 100, 100
        pos: 20, (root.height - 90) / 2.0
        id: ball

main.kv

#:include kv/homescreen.kv
#:include kv/gamescreen.kv


GridLayout:
cols: 1
ScreenManager:
    id: screen_manager
    HomeScreen:
        name: "home_screen"
        id: home_screen
    GameScreen:
        name: "game_screen"
        id: game_screen

我做了另一个 kivy 项目并在没有屏幕的情况下尝试了同样的事情,它没有显示任何错误!这是我的代码

我的main.py

from kivy.app import App
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.properties import NumericProperty



class Ball(Image):
    velocity = NumericProperty(0)

    def on_touch_down(self, touch):
        self.source = "ball1.png"
        self.velocity = 275
        super().on_touch_down(touch)

    def on_touch_up(self, touch):
        self.source = "ball1.png"
        super().on_touch_up(touch)


class MainApp(App):
    GRAVITY = 300


    def move_ball(self, time_passed):
        ball = self.root.ids.ball
        ball.y = ball.y + ball.velocity * time_passed
        ball.velocity = ball.velocity - self.GRAVITY * time_passed


    def start_game(self):
        Clock.schedule_interval(self.move_ball, 1/60.)


MainApp().run()

main.kv

#:import utils kivy.utils

FloatLayout:
canvas:
    Color:
        rgb: utils.get_color_from_hex("#39B3F2")
    Rectangle:
        size: self.size
        pos: self.pos
GridLayout:
    rows: 1
    pos_hint: {"top": 1, "left": 1}
    size_hint: 1, .1
    Image:
        source: "sun.png"
GridLayout:
    rows: 1
    pos_hint: {"top": 1, "left": 1}
    size_hint: 1, .2
    Image:
        source: "clouds.png"
GridLayout:
    rows: 1
    pos_hint: {"bottom": 1, "left": 1}
    size_hint: 1, .5
    Image:
        source: "Field4.png"
        allow_stretch: True
        keep_ratio: False
        pos: self.pos

Button:
    text: "Start game"
    size_hint: None, None
    on_release:
        app.start_game()

Ball:
    source: "ball1.png"
    size_hint: None, None
    size: 100, 100
    pos: 20, (root.height - 90) / 2.0
    id: ball

我的第一个项目代码有什么问题?因为我的第二个似乎没有任何错误。

虽然这个问题没有完全显示回溯,但最后应该是这样的:

   File "C:\Users\weebi\Desktop\TestingZone\test1\kv\homescreen.kv", line 37, in <module>
     app.change_screen("game_screen")
   File "C:\Users\weebi\Desktop\TestingZone\test1\main.py", line 53, in change_screen
     screen_manager = self.root.ids.screen_manager
   File "kivy\properties.pyx", line 964, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

AttributeError: 'super' object has no attribute '__getattr__' 异常的原因通常与 .ids 列表中不存在的 id 有关。这是按预期工作的 change_screen 方法的更好版本:

def change_screen(self, screen_name):
    self.root.current = screen_name

还修复了您的 main.kv,以便它可以在屏幕之间正确切换

#:include kv/homescreen.kv
#:include kv/gamescreen.kv


ScreenManager:
    id: screen_manager
    HomeScreen:
        name: "home_screen"
        id: home_screen
    GameScreen:
        name: "game_screen"
        id: game_screen

顺便说一句,虽然这与问题不一定相关,但在尝试您的代码之前,我注意到了这一行:

ball = self.root.ids.ball

我继续检查 main.kv 文件,令我惊讶的是,没有 ID 为 ball 的根小部件,但 game_screen 对象中有一个,所以我的强迫症表现不佳,我为您解决了:

def move_ball(self, time_passed):
    ball = self.root.ids.game_screen.ids.ball
    ball.y = ball.y + ball.velocity * time_passed
    ball.velocity = ball.velocity - self.GRAVITY * time_passed