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

Kivy ScreenManager无法显示首个屏幕问题求助

问题原因及解决方案

核心问题在于:Kivy的Screen类没有build方法。当你将Login改为继承App时,build方法会被App的run()自动调用;但当Login作为Screen被添加到ScreenManager时,这个方法不会被执行,导致你创建的布局根本没有被添加到屏幕中,所以出现空白窗口。

修复方案一:修改Login类的初始化逻辑

将原有的build方法替换为__init__方法,同时完成父类初始化和布局添加:

from kivy.uix.screenmanager import Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
import json

class Login(Screen):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)  # 必须调用父类初始化方法,保证Screen正常工作
        
        self.window = GridLayout()
        self.window.cols = 1
        self.window.size_hint = (0.6, 0.7)
        self.window.pos_hint = {"center_x": 0.5, "center_y": 0.5}

        self.window.add_widget(Image(
            source="logo.png",
            size_hint=(10, 10)
        ))

        self.username = Label(
            text="Username",
            font_size=50,
            bold=True
        )
        self.window.add_widget(self.username)

        self.userinp = TextInput(
            multiline=False,
            padding_y=(20, 20),
            size_hint=(1, 0.8)
        )
        self.window.add_widget(self.userinp)

        self.password = Label(
            text="Password",
            font_size=50,
            bold=True
        )
        self.window.add_widget(self.password)

        self.passwordinp = TextInput(
            multiline=False,
            size_hint=(1, 0.8)
        )
        self.window.add_widget(self.passwordinp)

        self.login = Button(
            text="Login",
            size_hint=(1, 0.8),
            bold=True
        )
        self.login.bind(on_press=self.callback)
        self.window.add_widget(self.login)

        self.add_widget(self.window)  # 将布局添加到Screen自身

    def callback(self, instance):
        print("button pressed")
        username = self.userinp.text
        password = self.passwordinp.text
        try:
            with open('passwords.json') as f:
                data = json.load(f)
        except FileNotFoundError:
            print("Error")
            return
        if username not in data:
            print('User not found')
            return
        elif data[username] != password:
            self.login.text = 'Incorrect password'
            return
        else:
            self.login.text = 'Login successful'
            self.cusername = username
            self.manager.current = "Home"  # 替换原错误的root.manager,使用Screen自身的manager属性

修复方案二:使用Kv语言定义布局(推荐)

这是Kivy官方推荐的方式,将布局与逻辑分离,代码更清晰:

from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
import json

# 内嵌Kv布局代码
Builder.load_string('''
<Login>:
    GridLayout:
        cols: 1
        size_hint: 0.6, 0.7
        pos_hint: {"center_x": 0.5, "center_y": 0.5}
        
        Image:
            source: "logo.png"
            size_hint: 10, 10
        
        Label:
            text: "Username"
            font_size: 50
            bold: True
        
        TextInput:
            id: userinp
            multiline: False
            padding_y: 20, 20
            size_hint: 1, 0.8
        
        Label:
            text: "Password"
            font_size: 50
            bold: True
        
        TextInput:
            id: passwordinp
            multiline: False
            size_hint: 1, 0.8
        
        Button:
            id: login_btn
            text: "Login"
            size_hint: 1, 0.8
            bold: True
            on_press: root.callback(self)
''')

class Login(Screen):
    def callback(self, instance):
        print("button pressed")
        username = self.ids.userinp.text
        password = self.ids.passwordinp.text
        try:
            with open('passwords.json') as f:
                data = json.load(f)
        except FileNotFoundError:
            print("Error")
            return
        if username not in data:
            print('User not found')
            return
        elif data[username] != password:
            self.ids.login_btn.text = 'Incorrect password'
            return
        else:
            self.ids.login_btn.text = 'Login successful'
            self.cusername = username
            self.manager.current = "Home"

class AppManager(App):
    def build(self):
        sm = ScreenManager()
        sm.add_widget(Login(name = "Login"))
        # sm.add_widget(home(name = "Home"))
        sm.current = "Login"
        return sm

if __name__ == '__main__':
    AppManager().run()

额外注意点

  • 必须调用super().__init__(**kwargs):否则Screen的核心功能无法正常初始化
  • 回调中的root.manager需改为self.manager:在Screen类中,self.manager直接指向所属的ScreenManager
  • 若使用Kv语言,可通过self.ids访问布局中的控件,无需在Python代码中手动创建实例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:07:01