如何为Kivy中动态生成的空白TextInput设置焦点
Got it, let's fix this! The key issue here is that your current code only checks the text values of the inputs, but doesn't keep track of the actual TextInput widgets themselves. To set focus on the first empty field, we need to reference those widgets directly.
Modified insert Method
Replace the insert method in your display class with this code:
def insert(self): rows = self.ids.rows # Iterate through rows in the order they appear (first added to last) for row_num, row in enumerate(reversed(rows.children), 1): # Collect TextInput widgets from the row (in display order: Value1, Value2) text_inputs = [] for ch in reversed(row.children): if isinstance(ch, TextInput): text_inputs.append(ch) ti_value1, ti_value2 = text_inputs # Check first TextInput (Value1) if ti_value1.text.strip() == "": print(f"row{row_num} TextInput 1 is required") ti_value1.focus = True return # Stop after finding the first empty field # Check second TextInput (Value2) if ti_value2.text.strip() == "": print(f"row{row_num} TextInput 2 is required") ti_value2.focus = True return # If all fields are filled, proceed with your logic here print("All inputs are valid!")
What Changed?
- Track TextInput Widgets: Instead of just collecting text values, we now store references to each
TextInputin the row. This lets us modify theirfocusproperty directly. - Early Exit: As soon as we find the first empty field, we set focus on it and return immediately—so the user is taken straight to the missing input.
- Whitespace Handling: Using
strip()ensures that fields with only spaces are treated as empty (you can remove this if you want to allow whitespace-only inputs).
Full Modified test.py
Here's the complete updated test.py for reference (I fixed a small issue with the App's build method too):
from kivy.uix.screenmanager import Screen from kivy.app import App from kivy.lang import Builder from kivy.core.window import Window from kivy.uix.boxlayout import BoxLayout from kivy.properties import StringProperty from kivy.uix.textinput import TextInput from kivy.uix.button import Button Window.size = (450, 525) # Explicitly load the kv file (avoids issues with auto-loading) Builder.load_file('test.kv') class display(Screen): def add_more(self): self.ids.rows.add_row() def insert(self): rows = self.ids.rows # Iterate through rows in the order they appear (first added to last) for row_num, row in enumerate(reversed(rows.children), 1): # Collect TextInput widgets from the row (in display order: Value1, Value2) text_inputs = [] for ch in reversed(row.children): if isinstance(ch, TextInput): text_inputs.append(ch) ti_value1, ti_value2 = text_inputs # Check first TextInput (Value1) if ti_value1.text.strip() == "": print(f"row{row_num} TextInput 1 is required") ti_value1.focus = True return # Stop after finding the first empty field # Check second TextInput (Value2) if ti_value2.text.strip() == "": print(f"row{row_num} TextInput 2 is required") ti_value2.focus = True return # If all fields are filled, proceed with your logic here print("All inputs are valid!") class Row(BoxLayout): button_text = StringProperty("") def count_row(self): print('count row') class Rows(BoxLayout): orientation = "vertical" row_count = 0 def __init__(self, **kwargs): super(Rows, self).__init__(**kwargs) self.add_row() def add_row(self): self.row_count += 1 self.add_widget(Row(button_text=str(self.row_count))) class test(App): def build(self): return display() test().run()
Quick Note on Kivy Widget Order
Remember that Kivy stores children in reverse order of their appearance (the last widget added is first in the list). That's why we use reversed() when iterating through rows and row children—to get the order that matches what the user sees on screen.
内容的提问来源于stack exchange,提问作者Nirdesh Kumawat

