You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KivyMD条件切换屏幕报'super' object无__getattr__属性错误

问题根因

你遇到的'super' object has no attribute '__getattr__'报错和标注的切屏代码行无关,核心是几个错误叠加导致的:

  • self.root指向你在build里返回的ScreenManager实例,而user、password两个输入框的id是定义在login屏幕内部的,不属于ScreenManager的ids字典,跨层级访问不存在的id就会触发这个属性错误,报错位置只是刚好跑到切屏行之前的取值逻辑时触发,你误判了问题点。
  • build方法里初始屏幕直接设成了menu,打开APP直接进菜单,根本走不到登录流程。
  • kv文件里<menu>规则头漏了冒号,存在语法错误。
  • 你在py里手动实例化ScreenManager、重复给Screen传name参数的写法,和kv里的屏幕规则定义存在重复加载冲突。
修正方案

Kivy/KivyMD完全支持在Python代码里先做认证校验再切屏,所谓“必须在kv的on_release里直接绑定切屏”的说法是错的,只要正确访问组件id、拿到ScreenManager的引用,在任意逻辑节点都可以控制屏幕跳转。
修正后的代码如下:

Teste.py

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.dialog import MDDialog
from kivymd.uix.button import MDFlatButton
from kivy.uix.screenmanager import ScreenManager, Screen


class LoginScreen(Screen):
    pass
class MenuScreen(Screen):
    pass

class TestScreenManager(ScreenManager):
    pass

class LoginApp(MDApp):
    dialog = None
    def build(self):
        self.theme_cls.theme_style = "Light"
        self.theme_cls.primary_palette = "Indigo"
        self.theme_cls.accent_palette = "Blue"
        # 直接加载kv作为根组件,kv里已经定义好ScreenManager和挂载的屏幕
        return Builder.load_file('lteste.kv')
    
    def dialog_box(self):
        if not self.dialog:
            # 先拿到login屏幕实例,再访问它内部的输入框id
            login_screen = self.root.get_screen('login')
            self.dialog = MDDialog(
                title="Log In",
                text=f"Welcome {login_screen.ids.user.text}!",
                buttons=[
                    MDFlatButton(
                        text="Ok", 
                        text_color=self.theme_cls.primary_color,
                        on_release=self.close
                    ),
                ],
            )
        self.dialog.open()
    
    def validate_login(self):
        login_screen = self.root.get_screen('login')
        username = login_screen.ids.user.text
        password = login_screen.ids.password.text
        # 先做账号密码校验,通过后再切屏
        if username == '1' and password == '1':
            self.root.current = "menu"
            self.dialog_box()
    
    def close(self, instance):
        self.dialog.dismiss()
        

if __name__ == "__main__":
    LoginApp().run()

lteste.kv

# 根组件为ScreenManager,默认加载第一个挂载的login屏幕
TestScreenManager:
    LoginScreen:
        name: "login"
    MenuScreen:
        name: "menu"

<LoginScreen>:
    MDCard:
        size_hint: None, None
        size: 300, 600
        pos_hint: {"center_x": 0.5, "center_y": 0.5}
        elevation: 10
        padding: 65
        spacing: 35
        orientation: 'vertical'
        MDIcon:
            icon: 'account'
            # 原代码透明度设为0会导致图标完全不可见,修正为不透明
            icon_color: 0, 0, 0, 1
            halign: 'center'
            font_size: 180
        MDTextFieldRound:
            id: user
            icon_left: "account-check"
            hint_text: "Usuário"
            foreground_color: 1, 0, 1, 1
            size_hint_x: None
            width: 220
            font_size: 20
            pos_hint: {"center_x": 0.5}
        MDTextFieldRound:
            id: password
            icon_left: "key-variant"
            hint_text: "Senha"
            foreground_color: 1, 0, 1, 1
            size_hint_x: None
            width: 220
            font_size: 20            
            pos_hint: {"center_x": 0.5}
            password: True
        MDFillRoundFlatButton:
            text: "ENTRAR"
            font_size: 15
            pos_hint: {"center_x": 0.5}
            on_press: app.validate_login()
        MDFillRoundFlatButton:
            text: "REGISTRAR-SE"
            font_size: 15
            pos_hint: {"center_x": 0.5}

<MenuScreen>:
    # 原代码此处漏了冒号,属于语法错误
    MDCard:
        size_hint: None, None
        size: 300, 600
        pos_hint: {"center_x": 0.5, "center_y": 0.5}
        elevation: 10
        padding: 65
        spacing: 35
        orientation: 'vertical'
        MDRaisedButton:
            text: "Test"
关键注意点
  • Kivy的ids作用域是和所属的根规则绑定的,不要跨层级直接从App.root访问嵌套在子屏幕里的组件id,先通过get_screen(屏幕名)拿到对应屏幕实例,再访问它内部的ids。
  • 不要同时在kv和py里重复实例化ScreenManager、重复添加屏幕组件,避免出现组件加载冲突。
  • 切屏逻辑没有强制要求写在kv里,只要能拿到正确的ScreenManager实例,在py里的任意业务逻辑节点都可以修改current属性实现跳转,完全适配先校验再跳转的场景。

内容的提问来源于stack exchange,提问作者Carlos Jooj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 04:03:36