Reputation: 31
I am trying to call text input from the Kivy TextInput widget into a Python function that will do heavy lifting for math and have it output on a Label widget next to the TextInput widget.
I'm very new to Kivy but my professor mentioned it and have been messing around with what it can do. Currently I'm having an issue saying that the specific variable that I'm trying to call doesn't exist. I have tried running a function in the Kivy code that would turn the input into an int for the Python function to call but it got messy real fast. Before I break what I have any further I'm asking advice. I'm not going to include the full code since its very long but these are the snippets that are being used.
import abilities
import races
import os
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
class AbilityDisplay(GridLayout):
def __init__(self, **kwargs):
super(AbilityDisplay, self).__init__(**kwargs)
self.cols = 3
if os.path.isfile("character1.txt"):
with open("character1.txt", "r") as f:
d = f.read().split(",")
character_name = d[0]
char_str = d[1]
else:
character_name = ''
char_str = ''
self.add_widget(Label(text = 'Name'))
self.name = TextInput(text = character_name, multiline = False)
self.add_widget(self.name)
self.add_widget(Label())
self.add_widget(Label(text = 'Strength'))
self.strength = TextInput(text = char_str, multiline = False)
self.add_widget(self.strength)
self.add_widget(Label(text = str(Player.p_strength())))
self.save = Button(text = 'Save')
self.save.bind(on_press = self.save_state)
self.add_widget(Label())
self.add_widget(self.save)
def save_state(self, instance):
character_name = self.name.text
char_str = self.strength.text
print(f"Saving {character_name}.")
with open("character1.txt", "w") as f:
f.write(f"{character_name},{char_str}")
class TheApp(App):
def build(self):
return AbilityDisplay()
class Player():
def p_strength():
strength_input = int(AbilityDisplay.strength())
racial_bonus = 0
s_total = strength_input + racial_bonus
s_modifier = abilities.strength(s_total)
return s_modifier
if __name__ == '__main__':
TheApp().run()
There is a bit more code that involves other "abilities" and the code for the math is in the abilities module that I built. The code above is intended to take the player input from the widget run it through the Player class which will do call the abilities module for the math. Then the last label widget will display the output number. If I input say 18 for the math the label should show 4. The problem is that I am getting an error code on starting the program saying that AbilityDisplay has no attribute. I'm having a hard time making this work without breaking the code entirely.
For those who play D&D this should look familiar.
Edit: I realized a few lines were missing.
Upvotes: 0
Views: 578
Reputation: 16041
During instantiation of Label
widget, it tried to populate Label
's text by invoking p_strength()
method, but Kivy has not completed its building process. Therefore, the attributes have value of None.
The solution is to make the following enhancements.
on_text_validate
(when player press 'enter' key) event to bind strength
/ TextInput
to invoke a new method, on_enter()
on_enter()
to invoke p_strength()
methodLabel
widget and assign it to self.result
Label(text = str(Player.p_strength()))
with self.result
self
and strength
to p_strength()
methodAbilityDisplay.strength()
with strength
class AbilityDisplay(GridLayout):
def __init__(self, **kwargs):
super(AbilityDisplay, self).__init__(**kwargs)
self.cols = 3
...
self.add_widget(Label(text='Strength'))
self.strength = TextInput(text=char_str, multiline=False)
self.strength.bind(on_text_validate=self.on_enter)
self.add_widget(self.strength)
self.result = Label()
self.add_widget(self.result)
...
def on_enter(self, instance):
# update result's text
self.result.text = str(Player().p_strength(instance.text))
...
class Player():
def p_strength(self, strength):
strength_input = int(strength)
racial_bonus = 0
s_total = strength_input + racial_bonus
s_modifier = abilities.strength(s_total)
return s_modifier
Upvotes: 1