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

Kivy中ScreenManager与App类分离时,如何通过Python代码实现按钮点击切换屏幕

在Python代码中实现Kivy屏幕切换的正确方式

你遇到的AttributeError: 'NoneType' object has no attribute 'current'问题,核心原因是在Python代码里调用self.manager时,当前Screen还没有被添加到ScreenManager实例中,导致self.manager是None。而KV语言中app.root.current能正常工作,是因为KV的规则系统会在Screen被正确挂载到ScreenManager后才处理控件的事件绑定。

解决方案:直接通过App实例获取ScreenManager

和KV里的app.root对应,在Python代码中可以通过App.get_running_app()获取当前运行的App实例,再访问其root属性(也就是你的WindowManager)来切换屏幕。这是最可靠的方式,不需要依赖self.manager的状态。

修改你的Python代码

首先导入App类,然后修改changer方法:

from kivy.app import App

class SubmitAll(Screen):
    # 注意:不要在类级别直接实例化Widget类(比如Price()、Order_full()),
    # 建议在__init__方法内或者用KV规则创建,避免生命周期问题
    ordered_products = []
    order = StringProperty(str(ordered_products))

    def __init__(self, **kwargs):
        Screen.__init__(self, **kwargs)
        b = Button(text="submit")
        # 绑定到changer方法
        b.bind(on_press=self.changer)
        self.add_widget(b)

    def submit_all(self):
        pass

    def changer(self, *args):
        # 直接通过App实例获取ScreenManager并切换屏幕
        App.get_running_app().root.current = 'order_review'
        print('yes')

为什么之前的self.manager会是None?

在SubmitAll的__init__方法执行时,这个Screen对象还只是被创建出来,并没有被添加到你的WindowManager中。只有当WindowManager完成对Screen的挂载后,self.manager才会被Kivy自动赋值为对应的ScreenManager实例。而你在__init__里绑定的按钮事件,如果在Screen挂载前就触发(虽然实际中可能不会,但代码逻辑上存在这个时机问题),就会导致报错。

额外建议

  1. 避免在类级别直接实例化Kivy Widget(比如你代码里的Price = Price()、ReviewLayout = ReviewLayout()),这会创建不属于任何界面树的孤立实例,容易引发不可预期的问题。应该在__init__方法内创建并添加,或者完全通过KV规则定义。
  2. 你的WindowManager里的switching_function方法写法有问题,应该是实例方法(需要self参数),而不是类方法:
class WindowManager(ScreenManager):
    def switching_function(self, *args):
        self.current = 'review'

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 02:44:09