I am currently building an app that serves as a travel expenses manager. I have a system in which the user writes the desired amount of the expense on an MDTextField, such expense will be recorded in an MDList and the total amount of requested expenses will be added to an MDTextField. For clarity I will post a screen shot:
All this system works correctly so far. However, there can be mistakes made by the user. I want the user to be able to delete an item from the MDList when the trash-can icon is pressed. At the same time, the amount of the deleted expenditure should be substracted from the total amount requested. (i.e. If the user deletes the element of Alimentación which had $1,000.00, the total amount requested after deletion should be $2000.0).
In my code I've been able to bind the on_pressed event of the icon to a remove_item function. Which succesfully does the desired substraction, and afterwards will show a success toast. However this is done without actually deleting the item from the MDList. As shown on the second screenshot, the total expenses amount is 0, nevertheless the MDList item has not been deleted (remove_widget function inside my remove_item function is not doing the desired action).
CODE FOR MINIMAL REPRODUCIBLE EXAMPLE:
Python code:
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.app import MDApp
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelOneLine
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.list import TwoLineIconListItem, IconLeftWidget
from kivymd.toast import toast
class ViaticosIconList(TwoLineIconListItem):
pass
class MyContentAliment(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_aliment_viaje.text) <= 3 and self.ids.monto_aliment_viaje.text.isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_aliment_viaje.text) == 4 and self.ids.monto_aliment_viaje.text.isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text[0] + "," +
self.ids.monto_aliment_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_aliment_viaje.text) == 5 and self.ids.monto_aliment_viaje.text.isnumeric():
self.ids.monto_aliment_viaje.text = "$" + self.ids.monto_aliment_viaje.text[:2] + "," +
self.ids.monto_aliment_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_aliment_viaje.text) > 5 and self.ids.monto_aliment_viaje.text.startswith('$') == False:
self.ids.monto_aliment_viaje.text = self.ids.monto_aliment_viaje.text[:-1]
def sumar_gasto(self):
if self.ids.monto_aliment_viaje.text == "":
pass
elif self.ids.monto_aliment_viaje.text.startswith('$'):
pass
else:
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
monto_total += float(self.ids.monto_aliment_viaje.text)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.apply_currency_format()
screen_list_view = MDApp.get_running_app().root.get_screen('travelManager').ids.viaticos_list
icon = IconLeftWidget(icon='delete')
add_item = ViaticosIconList(text=f"Alimentación Personal", secondary_text=self.ids.monto_aliment_viaje.text)
add_item.add_widget(icon)
icon.bind(on_press=self.remove_item)
screen_list_view.add_widget(add_item)
def remove_item(self, instance):
# Remove item once the trash icon is clicked (pendiente)
travel = MDApp.get_running_app().root.get_screen('travelManager')
travel.ids.viaticos_list.remove_widget(instance)
self.substract_expense()
self.show_toast()
def substract_expense(self):
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
substract_amount = self.ids.monto_aliment_viaje.text[1:-3].replace(',', '')
monto_total -= float(substract_amount)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.ids.monto_aliment_viaje.text = ''
def show_toast(self):
toast("Monto de Alimentación Personal eliminado de la solicitud")
class MyContentCasetas(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_casetas_viaje.text) <= 3 and self.ids.monto_casetas_viaje.text.isnumeric():
self.ids.monto_casetas_viaje.text = "$" + self.ids.monto_casetas_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_casetas_viaje.text) == 4 and self.ids.monto_casetas_viaje.text.isnumeric():
self.ids.monto_casetas_viaje.text = "$" + self.ids.monto_casetas_viaje.text[0] + "," +
self.ids.monto_casetas_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_casetas_viaje.text) == 5 and self.ids.monto_casetas_viaje.text.isnumeric():
self.ids.monto_casetas_viaje.text = "$" + self.ids.monto_casetas_viaje.text[:2] + "," +
self.ids.monto_casetas_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_casetas_viaje.text) > 5 and self.ids.monto_casetas_viaje.text.startswith('$') == False:
self.ids.monto_casetas_viaje.text = self.ids.monto_casetas_viaje.text[:-1]
def sumar_gasto(self):
if self.ids.monto_casetas_viaje.text == "":
pass
elif self.ids.monto_casetas_viaje.text.startswith('$'):
pass
else:
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
monto_total += float(self.ids.monto_casetas_viaje.text)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.apply_currency_format()
screen_list_view = MDApp.get_running_app().root.get_screen('travelManager').ids.viaticos_list
icon = IconLeftWidget(icon='delete')
add_item = ViaticosIconList(text=f"Casetas", secondary_text=self.ids.monto_casetas_viaje.text)
add_item.add_widget(icon)
icon.bind(on_press=self.remove_item)
screen_list_view.add_widget(add_item)
def remove_item(self, instance):
# Remove item once the trash icon is clicked (pendiente)
travel = MDApp.get_running_app().root.get_screen('travelManager')
travel.ids.viaticos_list.remove_widget(instance)
self.substract_expense()
self.show_toast()
def substract_expense(self):
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
substract_amount = self.ids.monto_casetas_viaje.text[1:-3].replace(',', '')
monto_total -= float(substract_amount)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.ids.monto_casetas_viaje.text = ''
def show_toast(self):
toast("Monto de Casetas eliminado de la solicitud")
class MyContentGasolina(BoxLayout):
def apply_currency_format(self):
# if len <= 3
if len(self.ids.monto_gas_viaje.text) <= 3 and self.ids.monto_gas_viaje.text.isnumeric():
self.ids.monto_gas_viaje.text = "$" + self.ids.monto_gas_viaje.text + '.00'
# n,nnn
elif len(self.ids.monto_gas_viaje.text) == 4 and self.ids.monto_gas_viaje.text.isnumeric():
self.ids.monto_gas_viaje.text = "$" + self.ids.monto_gas_viaje.text[0] + "," +
self.ids.monto_gas_viaje.text[1:] + '.00'
# nn,nnn
elif len(self.ids.monto_gas_viaje.text) == 5 and self.ids.monto_gas_viaje.text.isnumeric():
self.ids.monto_gas_viaje.text = "$" + self.ids.monto_gas_viaje.text[:2] + "," +
self.ids.monto_gas_viaje.text[2:] + '.00'
def limit_currency(self):
if len(self.ids.monto_gas_viaje.text) > 5 and self.ids.monto_gas_viaje.text.startswith('$') == False:
self.ids.monto_gas_viaje.text = self.ids.monto_gas_viaje.text[:-1]
def sumar_gasto(self):
if self.ids.monto_gas_viaje.text == "":
pass
elif self.ids.monto_gas_viaje.text.startswith('$'):
pass
else:
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
monto_total += float(self.ids.monto_gas_viaje.text)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.apply_currency_format()
screen_list_view = MDApp.get_running_app().root.get_screen('travelManager').ids.viaticos_list
icon = IconLeftWidget(icon='delete')
add_item = ViaticosIconList(text=f"Gasolina", secondary_text=self.ids.monto_gas_viaje.text)
add_item.add_widget(icon)
icon.bind(on_press=self.remove_item)
screen_list_view.add_widget(add_item)
def remove_item(self, instance):
# Remove item once the trash icon is clicked (pendiente)
travel = MDApp.get_running_app().root.get_screen('travelManager')
travel.ids.viaticos_list.remove_widget(instance)
self.substract_expense()
self.show_toast()
def substract_expense(self):
travel_manager = MDApp.get_running_app().root.get_screen('travelManager')
monto_total = float(travel_manager.ids.suma_solic_viaje.text[2:])
substract_amount = self.ids.monto_gas_viaje.text[1:-3].replace(',', '')
monto_total -= float(substract_amount)
travel_manager.ids.suma_solic_viaje.text = "$ " + str(monto_total)
self.ids.monto_gas_viaje.text = ''
def show_toast(self):
toast("Monto de Gasolina eliminado de la solicitud")
class LoginWindow(Screen):
pass
class TravelManagerWindow(Screen):
panel_container = ObjectProperty(None)
# EXPANSION PANEL PARA SOLICITAR GV
def set_expansion_panel(self):
self.ids.panel_container.clear_widgets()
# FOOD PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", content=MyContentAliment(),
panel_cls=MDExpansionPanelOneLine(text="Alimentacion")))
# CASETAS PANEL
self.ids.panel_container.add_widget(MDExpansionPanel(icon="food", cont