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

如何为Kivy中动态生成的空白TextInput设置焦点

Solution: Set Focus on First Empty 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?

  1. Track TextInput Widgets: Instead of just collecting text values, we now store references to each TextInput in the row. This lets us modify their focus property directly.
  2. 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.
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:10:06