问题
I am trying to access an instance variable named self.localId in my kivy screen and it keeps saying the saying the instance doesn't exist after i have initialised it. I know I have an error In my code but im having a hard time identifying it. is there a different way to initialising instances in a kivy screen? but here is my code. I would appreciate any help
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()
Traceback
[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'
回答1:
You have two __init__() methods in ProfileWindow. The second redefines, overwriting the first, and does not create the localId attribute. Your one and only __init__() method in ProfileWindow should be:
def __init__(self, **kwargs):
super(ProfileWindow, self).__init__(**kwargs)
self.localId = None
The next problem is that you are creating 3 instances of ProfileWindow. You only need one. So remove the line:
window = ProfileWindow()
and from your build() method in the App, remove:
self.page = ProfileWindow()
The ProfileWindow is created by the line in your code:
sm = Builder.load_file("kivy.kv")
any other use of ProfileWindow() creates a new instance of ProfileWindow that is not part of your GUI.
Next, you need to access the correct instance of ProfileWindow when you press the Login Button. To do that, make use of the ids in your kv file as:
on_release:
app.root.ids.page.sign_in_existing_user(email.text, password.text)
And, what I think is the final error, your print_localId() method tries to print the text attribute of localId, but it does not have such an attribute. Just change that method to:
def print_localId(self):
print(self.localId)
回答2:
When comparing with my code you miss the definition of localId in kivy.kv and you don't initiate the object as Property. So it would be:
Code:
class ProfileWindow(Screen):
localId = NumericProperty()
def __init__(self):
self.localId = None
test5.kv
<ProfileWindow>:
name: "page"
localId: localId
来源:https://stackoverflow.com/questions/59860705/how-can-you-initialise-an-instance-in-a-kivy-screen-widget