Python代码内Kivy界面与类关联问题:按钮无法调用类中函数
Python代码内Kivy界面与类关联问题:按钮无法调用类中函数
我来帮你解决这个按钮无法调用类函数的问题,核心原因是你在KV字符串里错误地直接调用了类的方法,而不是当前屏幕实例的方法,另外还有几个细节问题需要修正,下面一步步来:
1. 修正KV字符串中按钮的调用逻辑
你现在在按钮的on_press里直接调用LoginScreen.login(),这是在调用类的静态方法,但我们需要调用的是当前LoginScreen实例的方法,应该用root来指代当前屏幕实例,同时还要修正拼写错误(把LogingScreen写成LoginScreen的笔误):
# 替换LoginScreen里的按钮部分 MDRoundFlatButton: text: "log in" font_size: 20 pos_hint:{"center_x": 0.5} on_press: root.login() # 使用root指代当前LoginScreen实例 MDRoundFlatButton: text: "reset" font_size: 20 pos_hint:{"center_x": 0.5} on_press: root.reseting_login() # 同样用root调用实例方法
2. 移除LoginScreen中的build方法,改用__init__初始化资源
build方法是MDApp类的专属方法,Screen类不需要这个方法,你应该把数据库初始化逻辑放到__init__方法中,同时修正主题样式的设置方式:
class LoginScreen(Screen): def __init__(self, **kwargs): super().__init__(**kwargs) # 获取当前App的主题配置 app = MDApp.get_running_app() app.theme_cls.theme_style = "Dark" app.theme_cls.primary_palette = 'BlueGray' try: self.client = pymongo.MongoClient( "mongodb+srv://gyanyoni25:yonigyan@patnouv.hhopv.mongodb.net/?retryWrites=true&w=majority&appName=PatNouv" ) self.db = self.client["Users"] self.collection = self.db["Clients"] self.client.admin.command('ping') print("Successfully connected to MongoDB Atlas!") except ConnectionFailure as e: print(f"Connection failed during startup: {e}") self.ids.welcome_label.text = "Database Connection Error" except Exception as e: print(f"An unexpected error occurred during startup: {e}") self.ids.welcome_label.text = "Database Connection Error"
3. 修正控件引用方式
你在login和reseting_login方法里用了self.root.ids,但self.root指向的是ScreenManager,正确的应该直接用self.ids来获取当前屏幕内的控件:
def login(self): # 修正为self.ids获取当前屏幕的控件 name_data = self.ids.name.text number_data = self.ids.number.text password_data = self.ids.password.text if name_data and number_data and password_data: try: hashed_password = hashlib.sha256(password_data.encode()).hexdigest() user_data = { "name": name_data, "number": number_data, "password": hashed_password } self.collection.insert_one(user_data) print("Login Successful") self.ids.welcome_label.text = f"Hey, {name_data}" self.reseting_login() except ConnectionFailure as e: print(f"Connection error during login: {e}") self.ids.welcome_label.text = "Connection Error" except DuplicateKeyError as e: print(f"Duplicate key error: {e}") self.ids.welcome_label.text = "Username/Number already exists" except Exception as e: print(f"An error occurred during login: {e}") self.ids.welcome_label.text = "An error occurred" else: print("Please fill in all fields.") self.ids.welcome_label.text = "Please fill in all fields" def reseting_login(self): # 同样修正为self.ids self.ids.name.text = "" self.ids.number.text = "" self.ids.password.text = "" self.ids.welcome_label.text = "Welcome"
4. 删除重复的ScreenManager创建代码
你已经通过Builder.load_string(screen_helper)创建了完整的屏幕结构,不需要再手动创建ScreenManager并添加控件,删除这段冗余代码:
# 删除以下代码块 # sm = ScreenManager() # sm.add_widget(MenuScreen(name='menu')) # sm.add_widget(LoginScreen(name='Login')) # sm.add_widget(SignupScreen(name='SignUp'))
5. 规范App类命名(可选)
按照Python的PEP8规范,类名应该使用大驼峰命名法,把egy改为EgyApp,并添加启动代码:
class EgyApp(MDApp): def build(self): screen = Builder.load_string(screen_helper) return screen if __name__ == "__main__": EgyApp().run()
补充说明你尝试方法中的问题
- 你把
app.reseting_login()改成LoginScreen.reseting_login()仍然不对,因为这是在调用类方法,而我们需要的是当前屏幕实例的方法,root才是正确的指代 - 屏幕名称的一致性很重要,你在KV里给LoginScreen的name是
'Log in page',手动添加时又用了'Login',这会导致屏幕切换失败,删除手动添加的代码后就不会有这个问题了
备注:内容来源于stack exchange,提问作者capitaine yoyoytb
相关产品推荐
相关产品推荐

