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挂载前就触发(虽然实际中可能不会,但代码逻辑上存在这个时机问题),就会导致报错。
额外建议
- 避免在类级别直接实例化Kivy Widget(比如你代码里的
Price = Price()、ReviewLayout = ReviewLayout()),这会创建不属于任何界面树的孤立实例,容易引发不可预期的问题。应该在__init__方法内创建并添加,或者完全通过KV规则定义。 - 你的
WindowManager里的switching_function方法写法有问题,应该是实例方法(需要self参数),而不是类方法:
class WindowManager(ScreenManager): def switching_function(self, *args): self.current = 'review'
内容的提问来源于stack exchange,提问作者ChrisCross
相关产品推荐
相关产品推荐

