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

KivyMD跨Screen类传递变量异常:无法获取输入框内容

KivyMD屏幕间变量传递问题:获取初始值而非输入框内容

我在开发KivyMD应用时,遇到了屏幕间变量传递的问题。从HomeScreen切换到ResultsScreen时,获取到的是HomeScreen的__init__方法中定义的初始值"dog",而不是通过get_text函数获取的输入框内容。

我的Python脚本

from kivymd.app import MDApp, Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import StringProperty
from api import gen_5_images

# --- this changes the app's default background --- #
Window.clearcolor = (.9, .9, .9, 1)
Window.size = (400, 500)

class HomeScreen(Screen):
    source = StringProperty()
    def __init__(self, **kwargs): 
        super(HomeScreen, self).__init__(**kwargs)
        self.text = 'dog'

    def get_text(self):
        self.text = self.ids.input.text
        return self.text

class ResultsScreen(HomeScreen):
    source = StringProperty()
    def on_manager(self, *args):
        # gets run when manager property is changed
        self.urls = gen_5_images(self.manager.get_screen('home').text)
        self.source = self.urls[0]
        
class Main(MDApp):
    def build(self):
        Builder.load_file("layout.kv")
        sm = ScreenManager()
        sm.add_widget(HomeScreen(name='home'))
        sm.add_widget(ResultsScreen(name='results'))
        return sm

Main().run()

我的KV文件

#:import hex kivy.utils.get_color_from_hex
<HomeScreen>:
    name: 'home'
    MDFloatLayout:
        md_bg_color: hex('#003153') # background color
        MDLabel:
            text: "DreamGen"
            color: hex('#f5deb3')
            halign: "center"
            pos_hint: {"center_x": .5, "center_y": .9}
            font_size: "40sp"
            font_name: "Pacifico"
        MDTextField:
            id: input
            hint_text: "I had a dream..."
            hint_text_color_normal: hex("#00aae4")
            hint_text_color_focus: hex("#00aae4")
            helper_text_color_focus: hex("#00aae4")
            line_color_normal: hex('#003153') #make line color of background
            line_color_focus: hex('#003153') #make line color of background
            helper_text: "Write what comes to your mind"
            helper_text_mode: "on_focus"
            text_color_focus: hex('#add8e6') # color of text clicked
            text_color_normal: hex('#add8e6') # color of text without clicked
            mode: "rectangle"
            multiline: True
            size_hint_x: 0.7
            size_hint_y: 0.5
            pos_hint: {"center_x": .5, "center_y": .5}
        MDFillRoundFlatButton:
            text: "Generate"
            text_color: hex('#003153')
            md_bg_color: hex('#add8e6')
            pos_hint: {"center_x": .5, "center_y": .1}
            font_size: "15sp"
            on_release: 
                root.get_text()
                root.manager.current = "results"

<ResultsScreen>:
    name: 'results'
    MDFloatLayout:
        md_bg_color: hex('#003153') # background color
        MDLabel:
            text: "DreamGen"
            color: hex('#f5deb3')
            halign: "center"
            pos_hint: {"center_x": .5, "center_y": .9}
            font_size: "40sp"
            font_name: "Pacifico"
        AsyncImage:
            size_hint: None,None
            size: root.height, root.height
            source: root.source
            mipmap: True
        MDFillRoundFlatButton:
            text: "Try again!"
            text_color: hex('#003153')
            md_bg_color: hex('#add8e6')
            pos_hint: {"center_x": .5, "center_y": .1}
            font_size: "15sp"
            on_release: root.manager.current = "home"

问题原因

ResultsScreen的on_manager方法只会在屏幕首次被添加到ScreenManager时触发一次,后续切换屏幕不会重新执行。因此它读取的是HomeScreen初始化时的text默认值,而非用户输入后更新的最新值。

修复方案

方案1:监听屏幕进入事件,每次获取最新数据

修改ResultsScreen类,去掉不必要的继承,改用on_pre_enter事件(每次进入屏幕前都会触发)来获取最新的输入内容:

class ResultsScreen(Screen):  # 不再继承HomeScreen,保持屏幕独立性
    source = StringProperty()
    def on_pre_enter(self, *args):
        # 每次切换到该屏幕时,获取HomeScreen的最新text值
        home_screen = self.manager.get_screen('home')
        self.urls = gen_5_images(home_screen.text)
        self.source = self.urls[0]

方案2:使用Kivy Property实现响应式更新

将HomeScreen的text改为StringProperty,这样变量变化时可以自动被监听(可选,进一步优化数据传递):

class HomeScreen(Screen):
    source = StringProperty()
    text = StringProperty('dog')  # 用StringProperty替代普通变量

    def get_text(self):
        self.text = self.ids.input.text

然后ResultsScreen依然使用on_pre_enter方法获取最新值即可。

额外优化建议

  • 避免让ResultsScreen继承HomeScreen,两个屏幕是独立组件,继承会引入不必要的属性和方法,增加代码复杂度。
  • 可以在get_text方法中添加空值判断,避免传入空文本给gen_5_images函数导致异常。

内容的提问来源于stack exchange,提问作者Marco Rodrigues

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 14:10:35