Kivy开发中如何获取动态添加的TextInput等控件的内容
解决方案
Kivy的ids字典是kv文件解析阶段自动生成的,仅收录kv语法中明确定义了id:属性的控件,Python代码动态添加的控件不会自动录入该字典,也没必要强行往ids里塞,自己维护独立的控件引用存储即可,实现成本很低。
具体修改逻辑
- 在布局类初始化时新增独立存储结构,专门存动态生成的输入控件,推荐用嵌套列表/字典按人员序号分组,避免和kv原生生成的id混淆。
- 动态创建
TextInput控件时,把生成的控件对象存入上述存储结构,不要丢失控件引用。 - 后续需要读取输入内容时,直接遍历存储结构,取对应控件的
text属性即可。 - 可选优化:每次生成新的人员输入项前,先清空之前动态添加的控件和旧引用,避免用户重复触发生成时页面堆积冗余控件。
修改后的可运行代码
Python部分
import sys, os, pyautogui from kivy.app import App from kivy.resources import resource_add_path from kivy.uix.scrollview import ScrollView from kivy.uix.label import Label from kivy.uix.textinput import TextInput class MeuLayout(ScrollView): def __init__(self, **kwargs): super().__init__(**kwargs) # 独立存储动态生成的人员输入控件,格式:[{字段名: 输入框对象}, ...] self.dynamic_inputs = [] def criar_pessoa(self, numero): # 清空之前生成的动态控件:kv中固定写死的grid直接子节点共8个,仅删除索引8之后的动态内容 while len(self.ids.grid.children) > 8: child = self.ids.grid.children[8] self.ids.grid.remove_widget(child) self.dynamic_inputs.clear() if numero.isnumeric(): if int(numero) > 20: pyautogui.alert('Excedeu o valor limite!') else: person_count = int(numero) for i in range(1, person_count+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_input = TextInput(write_tab= False, multiline=False, size_hint_y=None, height=30) self.ids.grid.add_widget(nome_input) sobrenome_input = TextInput(write_tab= False,multiline=False, size_hint_y=None, height=30) self.ids.grid.add_widget(sobrenome_input) # 添加联系方式标签 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_input = TextInput(write_tab= False,multiline=False, size_hint_y=None, height=30) self.ids.grid.add_widget(email_input) telefone_input = TextInput(write_tab= False,multiline=False, size_hint_y=None, height=30) self.ids.grid.add_widget(telefone_input) # 添加分割线 self.ids.grid.add_widget(Label(text='___________________________________________________________', size_hint_y=None, height=100)) self.ids.grid.add_widget(Label(text='___________________________________________________________', size_hint_y=None, height=100)) # 将当前人员的所有输入框存入结构 self.dynamic_inputs.append({ 'nome': nome_input, 'sobrenome': sobrenome_input, 'email': email_input, 'telefone': telefone_input }) else: pyautogui.alert('Coloque apenas números!') self.ids.numero_pessoas.text = '' # 示例:读取所有动态输入框的值 def get_all_data(self): res = [] for person in self.dynamic_inputs: res.append({ 'nome': person['nome'].text, 'sobrenome': person['sobrenome'].text, 'email': person['email'].text, 'telefone': person['telefone'].text }) # 此处可替换为后续数据处理逻辑 print(res) return res class AppCadastro(App): def build(self): return MeuLayout() if __name__ == '__main__': if hasattr(sys, '_MEIPASS'): resource_add_path(os.path.join(sys._MEIPASS)) AppCadastro().run()
KV部分
原有KV代码无需改动,如果需要触发数据读取,可在GridLayout末尾新增提交按钮绑定上述方法:
Button: text: '提交信息' size_hint_y: None height: 50 on_press: root.get_all_data() Label: size_hint_y: None height: 100
补充说明
如果习惯用id访问的形式,也可以在创建控件后手动将对象塞入self.ids字典,例如self.ids[f'nome_{i}'] = nome_input,后续可通过self.ids['nome_1'].text的形式取值。但这种方式会将动态id和kv原生id混在同一字典中,项目规模变大后容易出现命名冲突,单独维护存储结构的可维护性更高。
内容的提问来源于stack exchange,提问作者Marckson Assis
相关产品推荐
相关产品推荐

