I am currently using Python and Kivy to create a simple app. I currently have a button where I want the button's text show the the sum of two other button's text. I'm not sure how to accomplish this.
I know text: only accepts strings, so I've tried using int()
and str()
hoping to convert the texts into something I can run. But the error I ran into is
TypeError: 'kivy.weakproxy.WeakProxy' object is not callable
#abilityscore.kv
<AbilityScore@Button>:
font_size: 32
color: 0, 0, 0, 1
size: 50, 50
background_normal: ''
background_color: 153, 102, 0, 1
<BlankButton@Button>:
size: 50, 50
background_normal: ''
background_color: 153, 102, 0, 0
<CalcGridLayout>:
cols: 7
rows: 7
padding: 10
spacing: 10
AbilityScore:
id: str
text: "8"
AbilityScore:
id: strmod
text: "1"
AbilityScore:
text: str.text + strmod.text
With the current code of using
text: str.text + strmod.text
the result I get is the button showing 81, when I was hopping it being 9. as mentioned before I also tried
str(int(str.text) + int(strmod.text))
but I got the "TypeError: 'kivy.weakproxy.WeakProxy' object is not callable" error. my hopes it to find a way so that I have
AbilityScore:
id: str
text: "8"
AbilityScore:
id: strmod
text: "1"
AbilityScore:
text: <some code here>
where <some code here>
returns the result of 9 being the sum of str.text
and strmod.text
.
I you have a close look onto str(int(str.text) + int(strmod.text))
, you'll see
str
(int(
str
.text) + int(strmod.text))
Once you name an object str
then you try to call the builtin function str
. Python doesn't see the function any more, because it's shadowed by the same-name object in the inner scope. I think that's what the error message tells you:
TypeError: 'kivy.weakproxy.WeakProxy' object is not callable
So, in short, it should be possible if you avoid name clashes: *)
AbilityScore:
id: a_str
text: "8"
AbilityScore:
id: b_str
text: "1"
AbilityScore:
text: str(int(a_str.text) + int(b_str.text))
*) You should keep in mind that strings can fail to be evaluated to numbers. In the given case this seem not to be an issue, because the text
values are provided by literals. If the values are produced at run time, you have to deal with non-numerical inputs, for instance in the way shown by PalimPalim .
You could do something like
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class CalcButton(Button):
@staticmethod
def to_num(s):
try:
float(s)
return float(s)
except ValueError:
return 0
kv_str = Builder.load_string(""" BoxLayout:
TextInput:
id: t1
TextInput:
id: t2
CalcButton:
text: str(self.to_num(t1.text) + self.to_num(t2.text))
""")
class MyApp(App):
def build(self):
return kv_str
if __name__ == '__main__':
MyApp().run()
You can make it pure kv if you import the function to_num into the kv file and do not get it via the class. See https://kivy.org/doc/stable/guide/lang.html#special-syntax
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.