You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在KivyMD的kv文件中调用Python条件函数实现屏幕切换?

问题解决:Kivy注册界面表单验证后切换屏幕无响应

核心问题定位

当前代码存在三个关键问题:

  • kv文件中调用submit方法时,错误引用方法对象而非调用方法,导致条件判断失效
  • SignupWindow的submit()函数包含多余的while True循环,逻辑异常
  • 未掌握在Python代码中获取并操作ScreenManager的正确方式

修复方案

1. 修正kv文件的按钮点击逻辑

原代码中on_release事件错误使用root.submit == True,这是在比较方法对象本身而非调用后的返回值。需改为调用方法,并调整代码缩进:

Button:
    id: signup_submit
    pos_hint: {"top": 0.1375, "x": 0.075}
    text: "Submit"
    size_hint: 0.85, 0.075
    on_release:
        if root.submit():
            app.root.current = "login"
            app.root.transition.direction = "left"
        else:
            # 可选:添加验证失败提示,比如弹出MDToast
            pass

2. 简化Python中的submit()函数

移除多余的while True循环,拆分验证逻辑让代码更清晰:

def submit(self):
    # 邮箱格式验证
    email_valid = self.email.text != "" and "@" in self.email.text and "." in self.email.text
    # 用户名验证
    username_valid = 2 < len(self.username.text) < 20 and re.match("^[A-Za-z0-9_-]*$", self.username.text) and checkAl(self.username.text)
    # 密码验证
    password_valid = (self.password.text == self.password_c.text and 
                     len(self.password.text) > 5 and 
                     checkNumAl(self.password.text))
    
    return email_valid and username_valid and password_valid

3. 可选:在Python代码中直接控制屏幕切换

如果希望完全在Python中处理页面跳转,可通过self.manager获取ScreenManager:

def submit(self):
    email_valid = self.email.text != "" and "@" in self.email.text and "." in self.email.text
    username_valid = 2 < len(self.username.text) < 20 and re.match("^[A-Za-z0-9_-]*$", self.username.text) and checkAl(self.username.text)
    password_valid = (self.password.text == self.password_c.text and 
                     len(self.password.text) > 5 and 
                     checkNumAl(self.password.text))
    
    if email_valid and username_valid and password_valid:
        self.manager.current = "login"
        self.manager.transition.direction = "left"
        return True
    return False

对应的kv按钮逻辑简化为:

on_release: root.submit()

4. 优化辅助验证函数

用Python内置的any()函数简化验证逻辑:

def checkNumAl(s):
    return any(c.isalpha() for c in s) and any(c.isdigit() for c in s)

def checkAl(s):
    return any(c.isalpha() for c in s)

完整修正代码

Python代码

from kivy.config import Config
Config.set('graphics', 'width', '321')
Config.set('graphics', 'height', '657')
import kivy
import kivymd
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
import re
from kivy.properties import StringProperty


def checkNumAl(s):
    return any(c.isalpha() for c in s) and any(c.isdigit() for c in s)

def checkAl(s):
    return any(c.isalpha() for c in s)

class SignupWindow(Screen):
    age = ObjectProperty(None)
    email = ObjectProperty(None)
    username = ObjectProperty(None)
    password = ObjectProperty(None)
    password_c = ObjectProperty(None)
    signup_submit = ObjectProperty(None)
    icon = StringProperty()


    def submit(self):
        email_valid = self.email.text != "" and "@" in self.email.text and "." in self.email.text
        username_valid = 2 < len(self.username.text) < 20 and re.match("^[A-Za-z0-9_-]*$", self.username.text) and checkAl(self.username.text)
        password_valid = (self.password.text == self.password_c.text and 
                         len(self.password.text) > 5 and 
                         checkNumAl(self.password.text))
        
        if email_valid and username_valid and password_valid:
            self.manager.current = "login"
            self.manager.transition.direction = "left"
            return True
        return False


class LoginWindow(Screen):
    pass


class MainWindow(Screen):
    pass


class WindowManager(ScreenManager):
    pass


class MyMainApp(MDApp):
    def build(self):
        return Builder.load_file("my.kv")


if __name__ == "__main__":
    MyMainApp().run()

kv文件

WindowManager:
    SignupWindow:
    MainWindow:
    LoginWindow:

<Label>:
    font_size: 40
    color: 0.3, 0.6, 0.7, 1
    size_hint: 0.8, 0.1

<Form@MDTextField>:
    font_size: 30
    color: 0.3, 0.6, 0.7, 1
    size_hint: 0.85, 0.075
    padding_x: 20
    padding_y: [self.height / 1.5 - (self.line_height / 1.5) * len(self._lines), 0]
    multiline: False
    write_tab: False
    mode: 'rectangle'

<IconListItem>
    IconLeftWidget:
        icon: root.icon

<SignupWindow>:
    name: "signup"
    age: age
    email: email
    username: username
    password: password
    password_c: password_c
    signup_submit: signup_submit

    MDFloatLayout:
        md_bg_color: 0.2, 0.8, 1, 0.6
        Label:
            pos_hint: {"top": 1, "x": 0.1}
            text: "Sign Up"

        Button:
            id: age
            text: "Year"
            font_size: 30
            size_hint: 0.17, 0.05
            pos_hint: {"top": 0.7375, "x": 0.075}
            on_parent: drop_content.dismiss()
            on_release: drop_content.open(self)
        DropDown:
            id: drop_content
            on_select: age.text = f'{args[1]}'
            Button:
                id: btn1
                size_hint_x: 0.85
                size_hint_y: None
                text: 'First Item'
                height: 35
                on_release: drop_content.select('First Item')
            Button:
                id: btn3
                size_hint_x: 0.85
                size_hint_y: None
                text: 'Second Item'
                height: 35
                on_release: drop_content.select('Third Item')

        Form:
            id: email
            pos_hint: {"top": 0.6375, "x": 0.075}
            hint_text: 'Email'
            on_text_validate: username.focus = True

        Form:
            id: username
            pos_hint: {"top": 0.5375, "x": 0.075}
            hint_text: 'Username'
            on_text_validate: password.focus = True

        Form:
            id: password
            pos_hint: {"top": 0.4375, "x": 0.075}
            hint_text: 'Password'
            password: True
            on_text_validate: password_c.focus = True
            max_text_length: 20
            min_text_length: 6

        MDCheckbox:
            size_hint: None, None
            size: "48dp", "48dp"
            pos_hint:{"top": 0.355, "x": 0.83}
            on_active:
                password.password = not password.password
                password_text.text = "Show password" if password.password else "Hide password"

        MDLabel:
            id: password_text
            text: "Show password"
            pos_hint: {"top": 0.3668, "x": .52}
            font_size: 30

        Form:
            id: password_c
            pos_hint: {"top": 0.3, "x": 0.075}
            hint_text: 'Confirm password'
            password: True

        MDCheckbox:
            size_hint: None, None
            size: "48dp", "48dp"
            pos_hint:{"top": 0.2175, "x": 0.83}
            on_active:
                password_c.password = not password_c.password
                password_c_text.text = "Show password" if password_c.password else "Hide password"

        MDLabel:
            id: password_c_text
            text: "Show password"
            pos_hint: {"top": .2293, "x": .52}
            font_size: 30

        Button:
            id: signup_submit
            pos_hint: {"top": 0.1375, "x": 0.075}
            text: "Submit"
            size_hint: 0.85, 0.075
            on_release: root.submit()

<LoginWindow>:
    name: "login"
    Button:
        text: "Go back"
        on_release:
            app.root.current = "signup"
            app.root.transition.direction = "right"

<MainWindow>:
    name: "main"

内容的提问来源于stack exchange,提问作者helpmeplz123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:24:59