问题
I am stuck with my code, could you please help? After I added on_press to my kv file and describe function update_label, I got error:
AttributeError: 'Button' object has no attribute 'update_label'.
Even if i change description of my function with simple print() function it doesn't works. Thanks in advance!
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.stacklayout import StackLayout
from kivy.uix.textinput import TextInput
Builder.load_file('spain2.kv')
class Box2(BoxLayout):
pass
class Box1(StackLayout):
pass
class Ex42App(App):
def update_label(self):
if self.l1.text == 'amar':
self.l2.text = "Translate: to love"
else:
self.l2.text = "Infinitive not founded"
def build(self):
return Box2()
if __name__=='__main__':
Ex42App().run()
spain2.kv:
<Box2>:
orientation: 'vertical'
Box1:
orientation: 'lr-tb'
size_hint: 1, .1
Label:
id: l1
text: 'Insert Infinitive'
size_hint: None, None
size: 150, 30
TextInput:
size_hint: None, None
size: 300, 30
Button:
text: 'Find'
size_hint: None, None
size: 150, 30
on_press: self.update_label
Label:
id: l2
text: 'some data'
size_hint: None, .9
回答1:
It seems that he does not know the meaning of self
, root
and app
inside a .kv, for this case consider the following code:
<A>:
property_a: self.a
property_a1: root.a1
B:
property_b: self.b
property_c1: root.b1
C:
property_c: self.c
property_c1: root.c1
As the language .kv is observed, it is declarative and there is a tree of hierarchy.
In this case the root
refers to the first element: <A>
.
Instead the self
refers to an element within the tree, in the case of self.a
refers to the property a
belongs to A
, in the case of self.c
refers to the property c
belongs to C
.
And in the case of app refers refers to the object that belongs to a class that inherits from App, and this object is unique, in your case app refers to the object Ex42App()
that inherits from Ex42App.
So root and self is relative to a hierarchy tree, for example we can place a more complex structure:
<A>:
B:
some_property1: self.a # self is B
some_property2: root.a # root is A
<Y>:
Z:
some_property1: self.a # self is Z
some_property2: root.a # root is Y
With the above we analyze your case, according to what your code says update_label
belongs to the Button
but that is not correct, it belongs to App
so you must use app
, on the other hand update_label
is a function so you must invoke it using ()
.
On the other hand in the code .py point out that l1
and l2
belongs to App
but this does not belong to App
but to Box2
, but l1
and l2
is only visible inside Box2
, so that it can be used outside of Box
you must expose them as properties, and finally Box2
is the widget that returns build()
and that element is accessed through self.root
.
Considering the above, the solution is:
*.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.stacklayout import StackLayout
Builder.load_file('spain2.kv')
class Box2(BoxLayout):
pass
class Box1(StackLayout):
pass
class Ex42App(App):
def update_label(self):
if self.root.l1.text == 'amar': # <--
self.root.l2.text = "Translate: to love" # <--
else:
self.root.l2.text = "Infinitive not founded" # <--
def build(self):
return Box2()
if __name__=='__main__':
Ex42App().run()
*.kv
<Box2>:
l1: l1 # <--
l2: l2 # <--
orientation: 'vertical'
Box1:
orientation: 'lr-tb'
size_hint: 1, .1
Label:
id: l1
text: 'Insert Infinitive'
size_hint: None, None
size: 150, 30
TextInput:
size_hint: None, None
size: 300, 30
Button:
text: 'Find'
size_hint: None, None
size: 150, 30
on_press: app.update_label() # <--
Label:
id: l2
text: 'some data'
size_hint: None, .9
来源:https://stackoverflow.com/questions/53113040/attributeerror-button-object-has-no-attribute-update-label