多文件Kivy项目跨屏幕更新元素报错的解决方案咨询
问题解决:AttributeError: 'Screen' object has no attribute 'update'
错误原因
你在main.py中给home屏幕嵌套了两层结构:先是一个原生Screen组件(id为home),然后把自定义的HomeScreen实例添加到这个原生Screen里。当你调用get_screen('home')时,获取到的是外层的原生Screen对象,而非你定义的带有update方法的HomeScreen实例,因此触发报错。
解决方案
直接让自定义的HomeScreen作为ScreenManager的子屏幕,不需要额外嵌套原生Screen容器。因为HomeScreen本身就是Screen的子类,完全可以直接作为独立屏幕使用。
修改步骤:
- 替换
main.py中KV代码的外层Screen为HomeScreen - 移除
ManagerScreen中手动添加HomeScreen的代码 - 修正
home.py中KV的按钮事件引用,确保正确访问内部的ScreenManager
修改后的代码片段:
main.py
from kivymd.app import MDApp from kivymd.uix.relativelayout import MDRelativeLayout from kivymd.uix.boxlayout import MDBoxLayout from kivy.lang import Builder from kivy.uix.screenmanager import ScreenManager, Screen from login import LoginScreen from home import HomeScreen Builder.load_string( """ <ManagerScreen>: Screen: id: login name: 'login' MDScreen: id: register name: 'register' HomeScreen: id: home name: 'home' """ ) class ManagerScreen(ScreenManager): def __init__(self, **kwargs): super(ManagerScreen, self).__init__(**kwargs) self.ids.login.add_widget(LoginScreen()) # 移除原有的self.ids.home.add_widget(HomeScreen()) class MainApp(MDApp): def build(self): sm = ManagerScreen() return sm if __name__ == '__main__': MainApp().run()
home.py(修正重复ID和事件引用)
from kivymd.app import MDApp from kivymd.uix.relativelayout import MDRelativeLayout from kivymd.uix.boxlayout import MDBoxLayout from kivy.lang import Builder from kivy.uix.screenmanager import ScreenManager, Screen import sqlite3 from loading import LoadImage Builder.load_string( """ #:import utils kivy.utils <HomeScreen>: MDBoxLayout: orientation: 'vertical' MDBoxLayout: size_hint_y: None height: first.height MDRaisedButton: id: first text: "Ecran 1" on_press: root.ids.sm.current = 'firstscreen' MDRaisedButton: id: second text: "Ecran 2" on_press: root.ids.sm.current = 'secondscreen' ScreenManager: id: sm Screen: id: firstscreen name: 'firstscreen' MDRelativeLayout: MDCard: orientation: 'vertical' md_bg_color: utils.get_color_from_hex('#3e55c9') MDLabel: id: lab markup: True MDRaisedButton: id: buttontext text: 'importer fichier' Screen: id: secondscreen name: 'secondscreen' """ ) class HomeScreen(Screen): def __init__(self, **kwargs): super(HomeScreen, self).__init__(**kwargs) def update(self): self.ids.lab.text = "Bienvenu Monsieur"
login.py(无需修改,现在get_screen('home')将获取正确实例)
from kivymd.app import MDApp from kivymd.uix.relativelayout import MDRelativeLayout from kivymd.uix.boxlayout import MDBoxLayout from kivy.lang import Builder import sqlite3 from loading import LoadImage Builder.load_string( """ <LoginScreen>: MDCard: size_hint: .5, .4 pos_hint: {'center_x':.5, 'center_y':.5} orientation: 'vertical' padding: 10 spacing: 10 MDTextField: id: username hint_text: "Nom d'utilisateur" MDTextField: id: pwd hint_text: "Mot de passe" MDRaisedButton: text: 'Connexion' pos_hint: {'center_x':.5} on_press: root.log_in() MDTextButton: text: "Créez un compte si vous n'en avez pas!" pos_hint: {'center_x':.5} on_press: root.parent.parent.current = 'register' """ ) class LoginScreen(MDRelativeLayout): def __init__(self, **kwargs): super(LoginScreen, self).__init__(**kwargs) def log_in(self): home_screen = self.parent.manager.get_screen('home') home_screen.update() self.parent.parent.current = 'home'
修改完成后,get_screen('home')将正确获取到带有update方法的HomeScreen实例,调用update()即可正常修改Label文本。
内容的提问来源于stack exchange,提问作者Borris Kouadja NIANGORAN
相关产品推荐
相关产品推荐

