'Changing the text of a button (from a child class) when a function is triggered in another child class. Kivy
Here I have program that calculates profit based on expenses and revenue.
It works just fine as shown in the image. What I'm trying to do is change the text of buttons in the bottom most boxlayout every time the calc()
function is triggered in the MyGrid()
class. I tried to use id's but I'm doing it wrong. Also I tried using the on_press
method in my .kv file but I actually want the button.text
to change EVERYTIME the calc()
is triggered irrespective of the button being pressed or not.
NOTE: only the MyGrid()
class and MyScroll: is worth looking at everything else works as expected
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.metrics import dp
Builder.load_file("sample1.kv")
class MyLayout(BoxLayout):
pass
class HeaderBox(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.size_hint = (1,0.1)
self.orientation = "horizontal"
self.headers = ["Name","Price","Quantity","Name","Price","Quantity"]
for i in range(6):
b = Button(text=str(self.headers[i]))
self.add_widget(b)
class MyGrid(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 6
self.textinputs=[0] #i put a 0 in that list so that my object indexing can start with 1
#made a diff list full of indexes so i can use them in my calculating algo
self.expense_price_index = [2,8,14,20,26,32,38,44,50,56]
self.expense_quantity_index = [3,9,15,21,27,33,39,45,51,57]
self.revenue_price_index = [5,11,17,23,29,35,41,47,53,59]
self.revenue_quantity_index = [6,12,18,24,30,36,42,48,54,60]
#initializing some values
self.expense_total = 0
self.revenue_total = 0
self.profit = 0
#making a grid full of textinputs and adding them to self.textinputs list
for i in range(60):
b = TextInput(multiline=False,font_size=dp(20),size_hint=(1,None),height=50)
b.bind(on_text_validate=self.calc) #binding a function to make my calculations
self.textinputs.append(b)
self.add_widget(b)
#FUNCTION THAT DOES THE CALCULATIONS
def calc(self,ti_instance):
default_quantity = 1
self.expense_total = 0
self.revenue_total = 0
# CALCULATING EXPENSE TOTAL
for i in self.expense_price_index:
if self.textinputs[i].text == "":
continue
elif self.textinputs[i+1].text == "":
self.expense_total += int(self.textinputs[i].text) * default_quantity
else:
self.expense_total += int(self.textinputs[i].text) * int(self.textinputs[i+1].text)
# CALCULATING REVENUE TOTAL
for i in self.revenue_price_index:
if self.textinputs[i].text == "":
continue
elif self.textinputs[i+1].text == "":
self.revenue_total += int(self.textinputs[i].text) * default_quantity
else:
self.revenue_total += int(self.textinputs[i].text) * int(self.textinputs[i+1].text)
# CALCULATING PROFIT DOING BASIC ARITHMETIC
self.profit = str(self.revenue_total - self.expense_total)
print("Profit: " + self.profit)
class MyScroll(ScrollView):
pass
class MyApp(App):
def build(self):
return MyLayout()
if __name__ == "__main__":
MyApp().run() ```
```#:import dt datetime.date
#:import dp kivy.metrics.dp
#:set navbar_button_color (59/255, 68/255, 75/255, 1)
<MyLayout>:
orientation: "vertical"
BoxLayout:
size_hint: 1,0.1
Button:
text: "Back"
size_hint: 0.1,1
Button:
text: "Home"
size_hint: 0.1,1
Button:
text: "Daily"
size_hint: 0.1,1
Button:
text: "Weekly"
size_hint: 0.1,1
Button:
text: "Monthly"
size_hint: 0.1,1
Label:
text: dt.today().strftime("%d %B %Y")
size_hint: 0.5,1
canvas.before:
Color:
rgb: 59/255, 78/255, 85/255,1
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint: 1,0.15
Button:
text: "EXPENSES"
Button:
text: "REVENUE"
HeaderBox:
MyScroll:
BoxLayout:
orientation:"horizontal"
size_hint: 1,0.2
BoxLayout:
orientation: "vertical"
Button:
text: "Expense Total:"
font_size: dp(20)
on_press:
self.text: "Expense Total: " + str(my_grid.expense_total)
Button:
text: "Revenue Total:"
font_size: dp(20)
on_press:
self.text: "Revenue Total: " + str(my_grid.revenue_total)
Button:
text: "Profit:"
font_size: dp(40)
on_press:
self.text: "Profit: " + str(my_grid.profit)
<MyScroll>:
my_grid: my_grid
MyGrid:
id: my_grid
size_hint: 1, None
height: self.minimum_height```
#for @ApuCoder
```Button:
id: revenue_button
text: "Revenue Total: "
font_size: dp(20)
on_press:
self.text = "Revenue Total: " + str(my_grid.revenue_total)```
```class MyGrid(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
expense_button = ObjectProperty()```
```# CALCULATING PROFIT DOING BASIC ARITHMETIC
self.profit = str(self.revenue_total - self.expense_total)
self.expense_button.text = "Expense Total: " + str(self.expense_total) <-----
print("Profit: " + self.profit) ``````
Solution 1:[1]
You can access your MyGrid
in python
or kvlang
by creating a reference. One of the few ways is simply using an id
.
With this and other necessary modifications your full code in kvlang
looks like,
#:import dt datetime.date
#:import dp kivy.metrics.dp
#:set navbar_button_color (59/255, 68/255, 75/255, 1)
<MyLayout>:
orientation: "vertical"
BoxLayout:
size_hint: 1,0.1
Button:
text: "Back"
size_hint: 0.1,1
Button:
text: "Home"
size_hint: 0.1,1
Button:
text: "Daily"
size_hint: 0.1,1
Button:
text: "Weekly"
size_hint: 0.1,1
Button:
text: "Monthly"
size_hint: 0.1,1
Label:
text: dt.today().strftime("%d %B %Y")
size_hint: 0.5,1
canvas.before:
Color:
rgb: 59/255, 78/255, 85/255,1
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint: 1,0.15
Button:
text: "EXPENSES"
Button:
text: "REVENUE"
HeaderBox:
MyScroll: # Add the grid directly here.
MyGrid:
id: my_grid
size_hint: 1, None
height: self.minimum_height
BoxLayout:
orientation:"horizontal"
size_hint: 1,0.2
BoxLayout:
orientation: "vertical"
Button:
# text: "Expense Total:"
text: "Expense Total: " + str(my_grid.expense_total)
font_size: dp(20)
on_press:
self.text = "Expense Total: " + str(my_grid.expense_total)
Button:
# text: "Revenue Total:"
text: "Revenue Total: " + str(my_grid.revenue_total)
font_size: dp(20)
on_press:
self.text = "Revenue Total: " + str(my_grid.revenue_total)
Button:
# text: "Profit:"
text: "Profit: " + str(my_grid.profit)
font_size: dp(40)
on_press:
self.text = "Profit: " + str(my_grid.profit)
#<MyScroll>:
# my_grid: my_grid
# MyGrid:
# id: my_grid
# size_hint: 1, None
# height: self.minimum_height
Now create some properties for those attributes using NumericProperty
in python
.
Modified full code in python
,
from kivy.uix.textinput import TextInput
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
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 NumericProperty
Builder.load_file("sample1.kv")
class MyLayout(BoxLayout):
pass
class HeaderBox(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.size_hint = (1,0.1)
self.orientation = "horizontal"
self.headers = ["Name","Price","Quantity","Name","Price","Quantity"]
for i in range(6):
b = Button(text=str(self.headers[i]))
self.add_widget(b)
class MyGrid(GridLayout):
expense_total = NumericProperty(0)
profit = NumericProperty(0)
revenue_total = NumericProperty(0)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 6
self.textinputs=[0] #i put a 0 in that list so that my object indexing can start with 1
#made a diff list full of indexes so i can use them in my calculating algo
self.expense_price_index = [2,8,14,20,26,32,38,44,50,56] # range(2, 60, 6)
self.expense_quantity_index = [3,9,15,21,27,33,39,45,51,57] # range(3, 60, 6) etc.
self.revenue_price_index = [5,11,17,23,29,35,41,47,53,59]
self.revenue_quantity_index = [6,12,18,24,30,36,42,48,54,60]
#initializing some values
# self.expense_total = 0
# self.revenue_total = 0
# self.profit = 0
#making a grid full of textinputs and adding them to self.textinputs list
for i in range(60):
b = TextInput(multiline=False,font_size=dp(20),size_hint=(1,None),height=50)
b.bind(on_text_validate=self.calc) # binding a function to make my calculations
# b.bind(text=self.calc) # Bound to the property text.
self.textinputs.append(b)
self.add_widget(b)
#FUNCTION THAT DOES THE CALCULATIONS
def calc(self,ti_instance):
# def calc(self,ti_instance, text): # If bound to the property text.
default_quantity = 1
self.expense_total = 0
self.revenue_total = 0
# CALCULATING EXPENSE TOTAL
for i in self.expense_price_index:
if self.textinputs[i].text == "":
continue
elif self.textinputs[i+1].text == "":
self.expense_total += int(self.textinputs[i].text) * default_quantity
else:
self.expense_total += int(self.textinputs[i].text) * int(self.textinputs[i+1].text)
# CALCULATING REVENUE TOTAL
for i in self.revenue_price_index:
if self.textinputs[i].text == "":
continue
elif self.textinputs[i+1].text == "":
self.revenue_total += int(self.textinputs[i].text) * default_quantity
else:
self.revenue_total += int(self.textinputs[i].text) * int(self.textinputs[i+1].text)
# CALCULATING PROFIT DOING BASIC ARITHMETIC
self.profit = self.revenue_total - self.expense_total
print("Profit: " + str(self.profit))
class MyScroll(ScrollView):
pass
class MyApp(App):
def build(self):
return MyLayout()
if __name__ == "__main__":
MyApp().run()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |