here i've made a grid full of inputboxes using for-loop and added them to a dictionary to access later since i couldn't set id's in the python file. Now i'm trying to make a function that will make basic calculations based on the inputbox's data but i do not know how i can pass particular inputboxes in that function without using id's. Also the on_text function isn't working as i expected. I'm sure i'm missing something big here. Any guidance is appreciated.
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import StringProperty
Builder.load_file("gridtable.kv")
class MyBox(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
pass
class MyGrid(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols=6
self.textinputs = {}
for i in range(48):
key = i 1
self.textinputs[key] = TextInput(multiline=False,font_size=dp(30),on_text=self.calc(key))
self.add_widget(self.textinputs[key])
def calc(self,key):
print(self.textinputs[key])
class MyApp(App):
def build(self):
return MyBox()
if __name__ == "__main__":
MyApp().run()
<MyBox>:
mygrid:my_grid
orientation: "vertical"
MyGrid:
id: my_grid
size_hint: 1,0.8
BoxLayout:
orientation: "horizontal"
size_hint: 1,0.2
BoxLayout:
orientation: "vertical"
Button:
text: "Expense Total:"
Button:
text: "Revenue Total:"
Button:
text: "Profit:"
font_size: 40
Traceback (most recent call last):
File "c:\Users\jaika\OneDrive\Desktop\python\lil_curry_project\gridtable.py", line 38, in <module>
MyApp().run()
print(self.textinputs[key])
KeyError: 1
#better version of MyGrid()
class MyGrid(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols=4
self.textinputs = [0]
self.expense = 0
self.revenue = 0
self.profit = 0
for i in range(16):
t = TextInput(multiline=False,text=str(i 1))
t.bind(on_text_validate=self.calc_profit)
self.textinputs.append(t)
self.add_widget(t)
def calc_profit(self,instance):
index = self.textinputs.index(instance)
if index == 1 or index == 2 or index == 5 or index == 6 or index == 9 or index == 10 or index == 13 or index == 14:
self.expense = int(instance.text)
else:
self.revenue = int(instance.text)
self.profit = self.revenue - self.expense
print(self.profit)
CodePudding user response:
You can use bind
to trigger a method call, or use events available in the TextInput
(like on_text_validate
). Here is a modified MyGrid
class that uses both:
class MyGrid(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 6
self.textinputs = {}
for i in range(48):
key = i 1
self.textinputs[key] = TextInput(multiline=False, font_size=dp(30), on_text_validate=self.abba)
self.textinputs[key].bind(text=partial(self.calc, key))
print('in init, key =', key)
self.add_widget(self.textinputs[key])
def abba(self, ti_instance):
print('abba, textinput instance =', ti_instance, ', text =', ti_instance.text)
def calc(self, key, ti_instance, text):
print('calc:')
print('key =', key, ', text =', text, ', textinput instance =', ti_instance)
Note that the bind
to text
gets triggered with every change to the text in a TextInput
. The on_text_validate
will only be triggered when the user hits Enter
.