Python + Kivy(第二个屏幕正在加载空白)

Python + Kivy (second screen is loading blank)

我正在学习kivy...我正在为一个朋友开发我的第一个应用程序,一个非常简单的应用程序。但我面临这个错误:

每当我单击 "create account" 时,名为 'Login(Screen)' 的内容就会加载为空白。 None 我在我的 kivy 文件上创建的小部件显示。

代码如下:

============================================= =============================

python 文件:

from kivy.app import App

from kivy.uix.screenmanager import Screen, ScreenManager


class Gerenciador(ScreenManager):
    pass

class BoasVindas(Screen):
    pass

class Login(Screen):
    def logar(self, usuario, senha):
        print("usuario={0}, senha={1}".format(usuario, senha))

class Resultado(Screen):
    pass

class LoginApp(App):

    def build(self):
        return Gerenciador()

LoginApp().run()

============================================= ===========================

kivy 文件:

<Gerenciador>:
BoasVindas:
    name: 'boasvindas'
    BoxLayout:
        orientation:'vertical'
        Label:
            text:'Faça o seu Login ou crie uma nova conta'
        Button:
            text:'Login'

        Button:
            text:'Criar nova conta'
            on_release:root.current='login'


Login:
    name: 'login'
    BoxLayout:
        TextInput:
            id:usuario
            hint_text:'Usuário'
            multiline: False
        TextInput:
            id:senha
            hint_text:'Senha'  
            multiline: False
            password: True
        Button:
            id:'btn'
            text:'Ok'
            on_press: self.parent.parent.logar(usuario.text, senha.text)
            on_release:root.current='boasvindas'

============================================= ============================

关于我遗漏的任何想法?第一个屏幕加载完美。如果我交换订单,登录屏幕加载良好。但是第二个屏幕是空白的,不管是什么内容。只要是加载第二个屏幕,它 returns 空白。

谢谢!

Gerenciador__init__() 方法中,您正在创建 LoginBoasVindas 屏幕,但您也在 .kv 文件中创建它们.你不应该两者都做。如果您在 .kv 文件中创建它们,您的代码可能如下所示:

python 文件:

from kivy.app import App

from kivy.uix.screenmanager import Screen, ScreenManager


class Gerenciador(ScreenManager):
    pass

class BoasVindas(Screen):
    pass

class Login(Screen):
    pass

class Resultado(Screen):
    pass

class TesteLogin(App):

    def build(self):
       return Gerenciador()

TesteLogin().run()

kv 文件:

<Gerenciador>:
    BoasVindas:
        name: 'boasvindas'
        BoxLayout:
            orientation:'vertical'
            Label:
                text:'Faça o seu Login ou crie uma nova conta'
            Button:
                text:'Login'

            Button:
                text:'Criar nova conta'
                on_release:root.current='login'

    Login:
        name: 'login'
        BoxLayout:
            TextInput:
                id:usuario
                hint_text:'Usuário'
                multiline: False
            TextInput:
                id:senha
                hint_text:'Senha'
                multiline: False
                password: True
            Button:
                id:'btn'
                text:'Ok'
                #on_press:self.parent.parent.logar(usuario.text, senha.text)
                on_release:root.current='boasvindas'

在您的 .kv 文件中,当 class 名称被 <> 包围时,这意味着它是用于构建 class 的模板,但不是实际上创建 class。不带 <> 的 class 已创建,但 .kv 文件中的那些从属于 Gerenciador class。因此,当创建 Gerenciador class 的实例时(如在您的 App.build() 方法中),LoginBoasVindas 屏幕将作为其子屏幕创建。请注意,我将 name 属性添加到 .kv 文件中的那些屏幕。

问题 - 第二个屏幕空白

创建了四个屏幕。从 kv 文件创建了两个带有子部件且没有屏幕名称的屏幕。另外两个具有屏幕名称但没有子窗口小部件的屏幕是从 Python 代码创建的。

当按下按钮 'Criar nova conta' 以转到名称为 'login' 的屏幕时,它正在使用从 Python 代码创建的实例,该实例没有任何其中的小部件,即它是空白的。

Build/Processing 序列

在Kivy App中,处理顺序如下。为了证明这一点,将 print() 和 id() 函数添加到 kv 文件中,并为每个屏幕添加 Python 代码和 __init__() 方法。它将显示四个不同的屏幕和每个屏幕的内存位置。

  1. kv 文件始终是第一个处理的项目。
  2. Python代码是下一个要处理的项目。

片段:Python代码-证明Build/Processing序列

class Gerenciador(ScreenManager):

    def __init__(self):
        super(Gerenciador, self).__init__()
        print("\nGerenciador.__init__():", id(self), "\n")
        self.add_widget(Login(name='login'))
        self.add_widget(BoasVindas(name='boasvindas'))


class BoasVindas(Screen):

    def __init__(self, **kwargs):
        super(BoasVindas, self).__init__(**kwargs)
        print("\nBoasVindas.__init__():", id(self), "\n")


class Login(Screen):
    def __init__(self, **kwargs):
        super(Login, self).__init__(**kwargs)
        print("\nLogin.__init__():", id(self), "\n")


class TestLogin(App):

    def build(self):
        print("\nTestLogin.build():")
        return Gerenciador()

片段:文件-证明Build/Processing序列

        Button:
            text:'Criar nova conta'
            on_release:
                print("self.parent.parent=", self.parent.parent)
                print("id(self.parent.parent)=", id(self.parent.parent))
                print("app.root.screen_names=", app.root.screen_names)
                print("app.root.screens=", app.root.screens)
                for x in app.root.screens: print("screen={0}, id(screen)={1}".format(x, id(x)))
                root.current='login'

解决方案

详情请参考分步解决方案和示例。

Python代码

  1. pass
  2. 替换所有构造函数,__init__()方法

kv 文件

  1. name添加到每个屏幕,分别为name: 'boasvindas'name: 'login'
  2. self.parent.parent.logar(usuario.text, senha.text)替换为root.logar(usuario.text, senha.text)

例子

main.py

from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager


class Gerenciador(ScreenManager):
    pass


class BoasVindas(Screen):
    pass


class Login(Screen):

    def logar(self, usuario, senha):
        print("usuario={0}, senha={1}".format(usuario, senha))


class Resultado(Screen):
    pass


class TesteLogin(App):

    def build(self):
       return Gerenciador()


TesteLogin().run()

testelogin.kv

#:kivy 1.11.0

<Gerenciador>:
    BoasVindas:
        name: 'boasvindas'
        BoxLayout:
            orientation:'vertical'
            Label:
                text:'Faça o seu Login ou crie uma nova conta'  # Sign in or create a new account
            Button:
                text:'Login'

            Button:
                text:'Criar nova conta'     # Create new account
                on_release:root.current='login'

    Login:
        name: 'login'
        BoxLayout:
            TextInput:
                id:usuario
                hint_text:'Usuário'     # User
                multiline: False
            TextInput:
                id:senha
                hint_text:'Senha'   # Password
                multiline: False
                password: True
            Button:
                id:'btn'
                text:'Ok'
                on_press: self.parent.parent.logar(usuario.text, senha.text)
                on_release:root.current='boasvindas'    # Welcome

输出