Kivy通过App.get_running_app().root访问方法内变量报错排查
报错根因
你遇到的AttributeError: 'function' object has no attribute 'nome'由两个核心问题导致:
- 变量作用域不合法:
nome/sobrenome/email/telefone是定义在criar_pessoa方法内部的局部变量,仅在该方法执行过程中有效,方法运行结束后就会被回收,外部无法访问。你写的App.get_running_app().root.criar_pessoa.nome本质是试图给criar_pessoa这个函数对象读取不存在的属性,不符合Python语法规则。 - 隐藏逻辑bug:你创建邮箱、手机号输入框时,添加到布局中的是新生成的匿名
TextInput控件,并非你存入列表的email_pessoa、telefone_pessoa实例,后续就算能正常访问列表,拿到的也不是用户实际输入内容的控件。
修复步骤
- 将存储动态输入控件的列表改为
MeuLayout类的实例属性,用self.前缀定义,保证类内所有方法都可以访问。 - 修正邮箱、手机号输入框的添加逻辑,将存入列表的控件实例添加到布局中,不要新建匿名控件。
- 提交按钮的触发方法中,直接通过
self访问存储控件的实例属性即可,无需通过App.get_running_app()绕路获取根控件。
修复后核心代码
class MeuLayout(ScrollView): def criar_pessoa(self, numero): if numero.isnumeric(): if int(numero) > 20: pyautogui.alert('Excedeu o valor limite!') else: i=1 # 原局部变量改为类实例属性 self.nome = [] self.sobrenome = [] self.email = [] self.telefone = [] while i < int(numero)+1: self.ids.grid.add_widget(Label(text= f'Nome da {i}° pessoa:', size_hint_y= None, height= 100)) self.ids.grid.add_widget(Label(text=f'Sobrenome da {i}° pessoa:', size_hint_y=None, height=100)) nome_pessoa = TextInput(write_tab= False, multiline=False, size_hint_y=None, height=30) self.ids.grid.add_widget(nome_pessoa) self.nome.append(nome_pessoa) sobrenome_pessoa = TextInput(write_tab= False, multiline=False, size_hint_y=None, height=30) self.ids.grid.add_widget(sobrenome_pessoa) self.sobrenome.append(sobrenome_pessoa) self.ids.grid.add_widget(Label(text=f'Email da {i}° pessoa:', size_hint_y=None, height=100)) self.ids.grid.add_widget(Label(text=f'Telefone da {i}° pessoa:', size_hint_y=None, height=100)) email_pessoa = TextInput(write_tab= False, multiline=False, size_hint_y=None, height=30) # 修复:添加存入列表的控件实例,不要新建匿名控件 self.ids.grid.add_widget(email_pessoa) self.email.append(email_pessoa) telefone_pessoa = TextInput(write_tab= False, multiline=False, size_hint_y=None, height=30) # 修复:添加存入列表的控件实例,不要新建匿名控件 self.ids.grid.add_widget(telefone_pessoa) self.telefone.append(telefone_pessoa) i += 1 if i - 1 != int(numero): self.ids.grid.add_widget(Label(text='_'*60, size_hint_y=None, height=100)) self.ids.grid.add_widget(Label(text='_'*60, size_hint_y=None, height=100)) if i-1 == int(numero): self.ids.grid.add_widget(Label(text='', size_hint_y=None, height=100)) botao = Button(text='Iniciar', size_hint_y= None, height= 50, on_release = self.enviar) self.ids.grid.add_widget(botao) else: pyautogui.alert('Coloque apenas números!') self.ids.numero_pessoas.text = '' def enviar(self, widget): # 直接通过self访问实例上存储的控件列表 if self.nome: n = self.nome[0].text print(n) # 遍历四个列表即可拿到所有用户输入的姓名、姓氏、邮箱、手机号
优化建议:如果需要支持重复触发生成控件的逻辑,可以把动态生成的控件单独放在一个子GridLayout容器中,清空时只清空这个子容器即可,避免误删kv里定义的固定输入项。
内容的提问来源于stack exchange,提问作者Marckson Assis
相关产品推荐
相关产品推荐

