Kivy中Screen Manager无法通过按钮导航至新页面求助
Kivy多屏幕导航失败问题
我在Kivy中使用多屏幕架构,在名为Riddles的Screen内包含一个带有按钮的Riddlepage布局。尝试通过点击这些按钮,调用MainApp中定义的navigate函数跳转到Page2页面,绑定代码为b.bind(on_press=lambda x:MainApp().navigate("Page2")),但点击按钮后Screen Manager无法完成导航。
以下是部分代码:
class Page2(Screen): name="Page2" class Riddles(Screen): def __init__(self, **kwargs): super().__init__(**kwargs) class Riddlepage(BoxLayout): def __init__(self, **kwargs): self.pp = open("riddle.txt", "r") super().__init__(**kwargs) self.orientation = "vertical" self.spacing = dp(5) self.pos_hint = {"top": 1} for line in self.pp.readlines(): b = Button(text=line, size_hint=(.8, None), pos_hint={"x": .1}, height=(dp(40)),background_color=(0,0,1)) b.bind(on_press=lambda x:MainApp().navigate("Page2")) self.add_widget(b) self.pp.close() class MainApp(App): def __init__(self, **kwargs): super().__init__(**kwargs) with open("profile.txt", "r", encoding="utf-8") as file: self.info = file.readlines() self.sm=ScreenManager() def build(self): self.sm.add_widget(Page1(name="Page1")) self.sm.add_widget(Riddles(name="Riddles")) self.sm.add_widget(Coursewindow(name="Coursewindow")) self.sm.add_widget(Ancienwindow(name="Ancienwindow")) self.sm.add_widget(Level(name="Level")) self.sm.add_widget(Levels(name="Levels")) self.sm.add_widget(Corrections(name="Corrections")) self.sm.add_widget(Past_papers(name="Past_papers")) self.sm.add_widget(Page2(name="Page2")) self.sm.add_widget(Page3(name="Page3")) self.sm.add_widget(Profile(name="Profile")) return self.sm def navigate(self,p): self.sm.add_widget(Page2()) self.sm.current="Page2" return self.sm MainApp().run()
问题根源
- 错误创建新的MainApp实例:
MainApp()在lambda中会生成一个全新的App实例,而非引用当前正在运行的实例。这个新实例的ScreenManager和界面上实际使用的完全无关,调用它的navigate函数自然无法影响当前界面导航。 - 重复添加Page2屏幕:
navigate函数里每次都调用self.sm.add_widget(Page2()),但build方法中已经添加过Page2(name="Page2"),重复添加会导致ScreenManager中存在多个同名屏幕,可能引发逻辑冲突。
修复方案
1. 获取当前运行的App实例
修改按钮绑定代码,使用App.get_running_app()获取当前正在运行的MainApp实例,而非创建新实例:
# 确保导入App类 from kivy.app import App # 在Riddlepage的__init__方法中修改绑定逻辑 b.bind(on_press=lambda x: App.get_running_app().navigate("Page2"))
2. 优化navigate函数
移除重复添加Page2的代码,直接切换到已存在的屏幕:
def navigate(self,p): self.sm.current = p # 直接使用传入的参数,无需硬编码页面名称 return self.sm
3. 完整修改后的Riddlepage类
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.metrics import dp class Riddlepage(BoxLayout): def __init__(self, **kwargs): # 使用with语句管理文件资源,避免泄漏 with open("riddle.txt", "r") as self.pp: super().__init__(**kwargs) self.orientation = "vertical" self.spacing = dp(5) self.pos_hint = {"top": 1} for line in self.pp.readlines(): b = Button(text=line, size_hint=(.8, None), pos_hint={"x": .1}, height=(dp(40)), background_color=(0,0,1)) b.bind(on_press=lambda x: App.get_running_app().navigate("Page2")) self.add_widget(b)
额外补充
确保Riddles屏幕正确添加Riddlepage布局:
class Riddles(Screen): def __init__(self, **kwargs): super().__init__(**kwargs) self.add_widget(Riddlepage())
内容的提问来源于stack exchange,提问作者Lord vic
相关产品推荐
相关产品推荐

