Kivy中ScreenManager跨屏提交TextInput值至ListView问题求助
解决Kivy ScreenManager跨屏访问ListView的问题
嘿,我明白你遇到的问题了!你现在的核心困扰是跨屏幕访问其他Screen的控件属性——ProfileScreen里直接调用self.student_list肯定会报错,因为student_list是MainScreen独有的属性,ProfileScreen本身并没有这个东西。继承MainScreen虽然能拿到属性,但会连带继承界面元素,这显然不符合你的需求。
错误原因分析
你在ProfileScreen的okay方法里尝试用self.student_list,但self指的是当前ProfileScreen实例,它根本没有student_list这个属性,所以程序会抛出"ProfileScreen has no attribute 'student_list'"的错误。
解决方案:通过ScreenManager获取目标Screen实例
幸运的是,你已经在Manager类里定义了main_screen和profile_screen这两个ObjectProperty,并且在kv文件中正确绑定了对应的Screen实例。这意味着你可以通过self.manager拿到ScreenManager,再通过它获取MainScreen的实例,进而访问student_list。
修改ProfileScreen的okay方法即可:
def okay(self): abc_name = self.abc_text_input.text + " " + self.def_text_input.text # 通过ScreenManager获取MainScreen的实例 main_screen_instance = self.manager.main_screen # 操作MainScreen里的ListView main_screen_instance.student_list.adapter.data.extend([abc_name]) main_screen_instance.student_list._trigger_reset_populate()
修改后的完整Python代码
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.properties import ObjectProperty from kivy.uix.listview import ListItemButton from kivy.uix.screenmanager import ScreenManager, Screen class StudentListButton(ListItemButton): pass class Manager(ScreenManager): main_screen = ObjectProperty() profile_screen = ObjectProperty() class MainScreen(Screen): first_name_text_input= ObjectProperty() last_name_text_input= ObjectProperty() student_list = ObjectProperty() def submit_student(self): # Get the student name from the TextInputs student_name = self.first_name_text_input.text + " " + self.last_name_text_input.text # Add the student to the ListView self.student_list.adapter.data.extend([student_name]) # Reset the ListView self.student_list._trigger_reset_populate() def delete_student(self, *args): if self.student_list.adapter.selection: # Get the text from the item selected selection = self.student_list.adapter.selection[0].text # Remove the matching item self.student_list.adapter.data.remove(selection) # Reset the ListView self.student_list._trigger_reset_populate() def replace_student(self, *args): # If a list item is selected if self.student_list.adapter.selection: # Get the text from the item selected selection = self.student_list.adapter.selection[0].text # Remove the matching item self.student_list.adapter.data.remove(selection) # Get the student name from the TextInputs student_name = self.first_name_text_input.text + " " + self.last_name_text_input.text # Add the updated data to the list self.student_list.adapter.data.extend([student_name]) # Reset the ListView self.student_list._trigger_reset_populate() class ProfileScreen(Screen): abc_text_input=ObjectProperty() def_text_input=ObjectProperty() def okay(self): abc_name = self.abc_text_input.text + " " + self.def_text_input.text # 获取MainScreen实例 main_screen_instance = self.manager.main_screen # 添加到MainScreen的ListView main_screen_instance.student_list.adapter.data.extend([abc_name]) # 重置ListView main_screen_instance.student_list._trigger_reset_populate() class StudentDBApp(App): def build(self): return Manager() if __name__=="__main__": StudentDBApp().run()
补充说明
- 这种方式的核心是利用
ScreenManager作为中间层,管理所有Screen实例,这样任意一个Screen都可以通过self.manager访问到其他Screen的实例。 - 如果你没有在
Manager里定义main_screen属性,也可以通过self.manager.get_screen("main_screen")来获取目标Screen(这里的"main_screen"是你在kv文件中给MainScreen设置的name属性),效果是一样的。比如:main_screen_instance = self.manager.get_screen("main_screen")
这样修改后,你点击ProfileScreen的"Okay"按钮就能正常把内容添加到MainScreen的ListView里,而且不会继承多余的界面元素啦!
内容的提问来源于stack exchange,提问作者Kadir Karadavut
相关产品推荐
相关产品推荐

