如何在 Kivy 屏幕小部件中初始化实例

Posted

技术标签:

【中文标题】如何在 Kivy 屏幕小部件中初始化实例【英文标题】:How can you initialise an instance in a Kivy screen widget 【发布时间】:2020-05-08 16:06:43 【问题描述】:

我试图在我的 kivy 屏幕中访问一个名为 self.localId 的实例变量,它一直说在我初始化后实例不存在。我知道我的代码中有一个错误,但我很难识别它。在 kivy 屏幕中初始化实例有不同的方法吗?但这是我的代码。我会很感激任何帮助

mainfile.py

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



class LoginWindow(Screen):
   pass


class ProfileWindow(Screen):


   def __init__(self):
       self.localId = None






   def sign_in_existing_user(self, email, password):
       signin_url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=" + self.wak
       signin_payload = "email": email, "password": password, "returnSecureToken": True
       signin_request = requests.post(signin_url, data=signin_payload)
       sign_up_data = json.loads(signin_request.content.decode())
       app = App.get_running_app()
       print(signin_request.ok)
       print(signin_request.content.decode())

       if signin_request.ok == True:
           refresh_token = sign_up_data['refreshToken']

           self.localId = sign_up_data['localId']
           idToken = sign_up_data['idToken']
           # Save refreshToken to a file
           with open(app.refresh_token_file, "w") as f:
               f.write(refresh_token)

               print(sign_up_data['localId'])



           app.root.current = "page"

       elif signin_request.ok == False:
           error_data = json.loads(signin_request.content.decode())
           error_message = error_data["error"]['message']
           app.root.ids.login.ids.login_message.text = error_message.replace("_", " ")



   def print_localId(self):
       print(self.localId.text)


   def __init__(self, **kwargs):
       super(ProfileWindow, self).__init__(**kwargs)




window = ProfileWindow()




class MyApp(App):
   refresh_token_file = "refresh_token.txt"


   def build(self):
       self.page = ProfileWindow()
       self.refresh_token_file = self.user_data_dir + self.refresh_token_file

       return sm


class WindowManager(ScreenManager):
   pass


sm = Builder.load_file("kivy.kv")

#sm = WindowManager() 

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

kivy.kv

WindowManager:
   id: window manager
   LoginWindow:
       id: login
       name: "login"
   ProfileWindow:
       id: page
       name: "page"



<LoginWindow>

   canvas.before:
       Color:
           rgba: 1, 1, 1, 1
       Rectangle:
           pos: self.pos
           size: self.size


   TextInput:
       id: email
       hint_text: "Email"
       multiline: False
       pos_hint: "center_x": 0.2 , "center_y":0.9
       size_hint: 0.4, 0.10

   TextInput:
       id: password
       hint_text: "Password"
       multiline: False
       pos_hint: "center_x": 0.2, "center_y": 0.8
       size_hint: 0.4, 0.10
       password: True


   Button:
       pos_hint:"x":0.3,"y":0.05
       size_hint: 0.4, 0.1
       text: "Login"
       font_size: (root.width**2 + root.height**2)  / 14**4
       background_color: (0.082, 0.549, 0.984, 1.0)
       background_normal: ''
       on_release:
           app.page.sign_in_existing_user(email.text, password.text)

<ProfileWindow>:


   canvas.before:
       Color:
           rgba: 1, 1, 1, 1
       Rectangle:
           pos: self.pos
           size: self.size

   Button:
       pos_hint:"x":0.3,"y":0.05
       size_hint: 0.4, 0.1
       text: "Print localId"
       font_size: (root.width**2 + root.height**2)  / 14**4
       background_color: (0.082, 0.549, 0.984, 1.0)
       background_normal: ''
       on_release:
           root.print_localId()


追溯

[INFO   ] [Base        ] Leaving application in progress...
Traceback (most recent call last):
  File "/Users/temitayoadefemi/PycharmProjects/test6/mainfile.py", line 109, in <module>
    MyApp().run()
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/app.py", line 855, in run
    runTouchApp()
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/base.py", line 504, in runTouchApp
    EventLoop.window.mainloop()
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 747, in mainloop
    self._mainloop()
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 479, in _mainloop
    EventLoop.idle()
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/base.py", line 342, in idle
    self.dispatch_input()
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/base.py", line 327, in dispatch_input
    post_dispatch_input(*pop(0))
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/base.py", line 293, in post_dispatch_input
    wid.dispatch('on_touch_up', me)
  File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/uix/behaviors/button.py", line 179, in on_touch_up
    self.dispatch('on_release')
  File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
  File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
  File "kivy/_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
  File "/Users/temitayoadefemi/PycharmProjects/test6/venv/lib/python3.7/site-packages/kivy/lang/builder.py", line 64, in custom_callback
    exec(__kvlang__.co_value, idmap)
  File "/Users/temitayoadefemi/PycharmProjects/test6/kivy.kv", line 86, in <module>
    root.print_localId()
  File "/Users/temitayoadefemi/PycharmProjects/test6/mainfile.py", line 73, in print_localId
    print(self.localId.text)
AttributeError: 'ProfileWindow' object has no attribute 'localId'

【问题讨论】:

你为什么老是用不同的账户问同样的问题,然后又删除了其他的? @RandomUser 问题越近,得到的关注越多 关注标签的人很烦。即便如此,给它一些时间,耐心一点。今天也只问了同样的问题。删除它是对回答并试图提供帮助的人的不尊重。 请添加您的kv文件的竞争,因为它在错误消息中提到。 您的回溯表明您的 test5/kivy.kv 文件中有错误,但您尚未提供该文件。不查看该文件就无法判断问题所在。 【参考方案1】:

ProfileWindow 中有两个 __init__() 方法。第二个重新定义,覆盖第一个,并且不创建localId 属性。 ProfileWindow 中唯一的 __init__() 方法应该是:

   def __init__(self, **kwargs):
       super(ProfileWindow, self).__init__(**kwargs)
       self.localId = None

下一个问题是您要创建 3 个 ProfileWindow 实例。你只需要一个。所以删除该行:

window = ProfileWindow()

并从App 中的build() 方法中删除:

self.page = ProfileWindow()

ProfileWindow 由您的代码中的行创建:

sm = Builder.load_file("kivy.kv")

ProfileWindow() 的任何其他用途都会创建一个不属于您的 GUI 的 ProfileWindow 的新实例。

接下来,当您按下Login Button 时,您需要访问ProfileWindow 的正确实例。为此,请使用 kv 文件中的 ids

    on_release:
        app.root.ids.page.sign_in_existing_user(email.text, password.text)

而且,我认为是最后一个错误,您的print_localId() 方法试图打印localIdtext 属性,但它没有这样的属性。只需将该方法更改为:

   def print_localId(self):
       print(self.localId)

【讨论】:

爱你的兄弟,感谢所有帮助【参考方案2】:

与我的代码进行比较时,您错过了 kivy.kv 中 localId 的定义,并且您没有将对象作为属性启动。 所以应该是:

代码:

class ProfileWindow(Screen):
    localId = NumericProperty()

    def __init__(self):
        self.localId = None 

test5.kv

<ProfileWindow>:
    name: "page"
    localId: localId

【讨论】:

以上是关于如何在 Kivy 屏幕小部件中初始化实例的主要内容,如果未能解决你的问题,请参考以下文章

在子小部件中,如何在 kivy 中获取父小部件的实例

如何获取在kivy中定义在屏幕小部件内的滑块的值

如果未动态添加,如何正确删除Kivy中的小部件

向 Kivy 添加小部件时如何确保功能正常

如何将位于同一行的 Kivy 小部件移得更远?

kivy python 小部件实例或所有小部件