简体   繁体   中英

Can I perform simple math addition/subtraction in a button's text area in kivy?

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

Conclusion

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM