Contents

Hur man bygger en utgiftsspårare med Python

En utgiftsspårare är ett viktigt verktyg som hjälper privatpersoner och företag att hantera sina finansiella transaktioner. Med en utgiftsspårare kan du skapa budgetar, kategorisera utgifter och analysera utgiftsmönster.

Utforska metoder för att konstruera ett grafiskt användargränssnitt (GUI) för plattformar för att spåra utgifter med hjälp av Python-programmeringsspråket.

Modulerna Tkinter, CSV och Matplotlib

För att konstruera denna applikation för att spåra utgifter är det nödvändigt att använda biblioteken Tkinter, CSV och Matplotlib.

Tkinter gör det möjligt för utvecklare att skapa fängslande skrivbordsprogram genom att tillhandahålla en rad mångsidiga grafiska komponenter som knappar, etiketter och textinmatningsfält. Det användarvänliga gränssnittet förenklar processen att skapa applikationer för olika ändamål.

CSV-modulen är ett inbyggt Python-paket som erbjuder funktioner för tolkning och sammansättning av CSV-filer (Comma-Separated Value), som ofta används för att utbyta data mellan olika applikationer och system på grund av deras enkelhet och kompatibilitet med olika plattformar.

Matplotlib är ett kraftfullt verktyg för att skapa dynamiska visuella representationer, inklusive grafer, plottar och diagram, som kan förbättras ytterligare genom att integrera det med OpenCV för att få expertis inom avancerade bildmanipuleringstekniker.

För att installera dessa moduler, kör:

pip install tk matplotlib 

Definiera strukturen för appen Expense Tracker

Ursprunget till detta projekts källkod finns i dess GitHub-arkiv, som fungerar som en digital lagringsplats för alla tillhörande filer och dokumentation.

För att komma igång importerar vi imperativa moduler. Vi skapar sedan en klass som heter ExpenseTrackerApp , som anger applikationens titel och dimensioner. Därefter definierar vi ett ordnat par av listor; en som innehåller alla registrerade utgifter, medan den andra omfattar olika monetära kategorier. En strängvariabel, kallad category_var , upprättas också, med en initial inställning som motsvarar den främsta kategorin på vår lista. Slutligen använder vi proceduren create_widgets för att ta fram det grafiska användargränssnittet.

 import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import csv
import matplotlib.pyplot as plt

class ExpenseTrackerApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Expense Tracker")
        self.geometry("1300x600")
        self.expenses = []
        self.categories = [
            "Food",
            "Transportation",
            "Utilities",
            "Entertainment",
            "Other",
        ]
        self.category_var = tk.StringVar(self)
        self.category_var.set(self.categories[0])
        self.create_widgets()

Metoden create_widgets är en viktig komponent i konstruktionen av användargränssnitt i applikationer. För att skapa ett ramverk för visning av information som rör utgifter måste vi generera visuella element som består av ramar som rymmer specifika detaljer som är kopplade till dessa poster.Vi kommer att utveckla sex separata etikettwidgets, var och en utformad för att presentera relevanta data som rubriker, monetära värden, beskrivningar, kategorier, datum och totalsummor. Det är viktigt att tilldela ett överordnat element för varje etikett och samtidigt specificera deras respektive texter och typografiska egenskaper.

För att skapa ett gränssnitt med tre textingångar och en rullgardinsmeny, upprätta en koppling mellan den senare och en variabel med namnet category_var . Börja med att definiera layouten för vart och ett av dessa element; ange deras respektive teckensnittsstilar och dimensioner enligt följande:1. Skapa tre Entry-widgets och tilldela dem individuella parent containers, stylingalternativ och breddbegränsningar.2. Konstruera en Combobox-widget, definiera dess parent container, lista över tillgängliga val, teckensnitt och dimensionella specifikationer.3. Koppla Combobox till variabeln category_var , vilket säkerställer att valet i rullgardinsmenyn uppdateras i realtid baserat på användarens interaktion.

     def create_widgets(self):
        self.label = tk.Label(
            self, text="Expense Tracker", font=("Helvetica", 20, "bold")
        )
        self.label.pack(pady=10)
        self.frame_input = tk.Frame(self)
        self.frame_input.pack(pady=10)
        self.expense_label = tk.Label(
            self.frame_input, text="Expense Amount:", font=("Helvetica", 12)
        )
        self.expense_label.grid(row=0, column=0, padx=5)
        self.expense_entry = tk.Entry(
            self.frame_input, font=("Helvetica", 12), width=15
        )
        self.expense_entry.grid(row=0, column=1, padx=5)
        self.item_label = tk.Label(
            self.frame_input, text="Item Description:", font=("Helvetica", 12)
        )
        self.item_label.grid(row=0, column=2, padx=5)
        self.item_entry = tk.Entry(self.frame_input, font=("Helvetica", 12), width=20)
        self.item_entry.grid(row=0, column=3, padx=5)
        self.category_label = tk.Label(
            self.frame_input, text="Category:", font=("Helvetica", 12)
        )
        self.category_label.grid(row=0, column=4, padx=5)
        self.category_dropdown = ttk.Combobox(
            self.frame_input,
            textvariable=self.category_var,
            values=self.categories,
            font=("Helvetica", 12),
            width=15,
        )
        self.category_dropdown.grid(row=0, column=5, padx=5)
        self.date_label = tk.Label(
            self.frame_input, text="Date (YYYY-MM-DD):", font=("Helvetica", 12)
        )
        self.date_label.grid(row=0, column=6, padx=5)
        self.date_entry = tk.Entry(self.frame_input, font=("Helvetica", 12), width=15)
        self.date_entry.grid(row=0, column=7, padx=5) 

Skapa ett användargränssnitt med följande komponenter:En knapp med namnet “Lägg till utgift” som lägger till en utgift i en lista;En knapp med namnet “Redigera utgift” som redigerar en befintlig utgift i listan;En knapp med namnet “Radera utgift” som raderar en utgift från listan;En knapp med namnet “Spara utgifter” som sparar alla utgifter i listan;En knapp med namnet “Visa utgiftsdiagram” som visar ett diagram över utgifterna i listan;En ram runt dessa knappar med rubriken “Expense Manager”.

Införliva funktionen att skapa ett vertikalt rullningsfält som är placerat på höger sida av GUI:s huvudsakliga innehållsområde, vilket möjliggör sömlös navigering av innehållet i listboxen. Använd lämpliga utfyllnadstekniker för att säkerställa optimal visuell presentation. När du uppdaterar den totala etiketten med ny information ska du dessutom göra alla nödvändiga justeringar för att upprätthålla konsekvensen i gränssnittet.

         self.add_button = tk.Button(self, text="Add Expense", command=self.add_expense)
        self.add_button.pack(pady=5)
        self.frame_list = tk.Frame(self)
        self.frame_list.pack(pady=10)
        self.scrollbar = tk.Scrollbar(self.frame_list)
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.expense_listbox = tk.Listbox(
            self.frame_list,
            font=("Helvetica", 12),
            width=70,
            yscrollcommand=self.scrollbar.set,
        )
        self.expense_listbox.pack(pady=5)
        self.scrollbar.config(command=self.expense_listbox.yview)
        self.edit_button = tk.Button(
            self, text="Edit Expense", command=self.edit_expense
        )
        self.edit_button.pack(pady=5)
        self.delete_button = tk.Button(
            self, text="Delete Expense", command=self.delete_expense
        )
        self.delete_button.pack(pady=5)
        self.save_button = tk.Button(
            self, text="Save Expenses", command=self.save_expenses
        )
        self.save_button.pack(pady=5)
        self.total_label = tk.Label(
            self, text="Total Expenses:", font=("Helvetica", 12)
        )
        self.total_label.pack(pady=5)
        self.show_chart_button = tk.Button(
            self, text="Show Expenses Chart", command=self.show_expenses_chart
        )
        self.show_chart_button.pack(pady=5)
        self.update_total_label() 

Definiera funktionen för Expense Tracker

Införliva den givna kodsnutten i en befintlig applikations gränssnitt som ett sätt att registrera utgifter med angivna kategorier och datum, varefter validering av de inmatade uppgifterna läggs till i en dynamisk lista som visas i ett grafiskt användargränssnitt, vilket därefter tar bort alla ytterligare manuella datainmatningsskyldigheter från slutanvändaren.

I annat fall är det nödvändigt att visa ett meddelande som anger att värdena för “expense” och “date” inte kan vara tomma. Efter detta bör funktionsanropet till update\_total\_label utföras.

     def add_expense(self):
        expense = self.expense_entry.get()
        item = self.item_entry.get()
        category = self.category_var.get()
        date = self.date_entry.get()
        if expense and date:
            self.expenses.append((expense, item, category, date))
            self.expense_listbox.insert(
                tk.END, f"{expense} - {item} - {category} ({date})"
            )
            self.expense_entry.delete(0, tk.END)
            self.item_entry.delete(0, tk.END)
            self.date_entry.delete(0, tk.END)
        else:
            messagebox.showwarning("Warning", "Expense and Date cannot be empty.")
        self.update_total_label() 

För att ändra en befintlig utgift i en registerdatabas kan man implementera en metod som heter “edit\_expense”.Denna metod hämtar index för den valda posten och tar fram motsvarande kostnad. Därefter uppmanas användaren att ange ett nytt värde för utgiften via en dialogruta. Om användaren anger en ny utgift kommer metoden att uppdatera utgiftslistan med denna information. Slutligen anropar metoden funktionen “refresh\_list” samt subrutinen “update\_total\_label” för att säkerställa att alla ändringar återspeglas korrekt i programmet.

     def edit_expense(self):
        selected_index = self.expense_listbox.curselection()
        if selected_index:
            selected_index = selected_index[0]
            selected_expense = self.expenses[selected_index]
            new_expense = simpledialog.askstring(
                "Edit Expense", "Enter new expense:", initialvalue=selected_expense[0]
            )
            if new_expense:
                self.expenses[selected_index] = (
                    new_expense,
                    selected_expense[1],
                    selected_expense[2],
                    selected_expense[3],
                )
                self.refresh_list()
                self.update_total_label() 

För att implementera den funktionalitet som beskrivs i kodavsnittet kommer vi att definiera en metod som heter delete_expense som hämtar index för den valda posten och hämtar motsvarande utgift. Vi kommer sedan att skicka detta index till funktionen så att den kan raderas från listboxen. Efter detta kommer vi att anropa funktionen update_total_label för att säkerställa att totaletiketten uppdateras i enlighet med detta.

     def delete_expense(self):
        selected_index = self.expense_listbox.curselection()
        if selected_index:
            selected_index = selected_index[0]
            del self.expenses[selected_index]
            self.expense_listbox.delete(selected_index)
            self.update_total_label() 

Visst! Här är ett exempel på hur du kan implementera detta i Python med Flask och SQLAlchemy:pythonfrån flaskimport gffrån sqlalchemyimport create_engine, Column, Integer, String, ForeignKeyfrån sqlalchemy.ormimport sessionmaker, relationshipfrån datetimeimport datetimeclass User(db.Model): tablename = ‘users’id = Column(‘id’, Integer, primary_key=True)name = Column(’name’, String)email = Column(’email’, String)created_at = Column(‘created_at’, DateTime, default=datetime.utcnow)updated_at = Column(‘updated_at’, DateTime, onupdate=datetime.utcnow)

     def refresh_list(self):
        self.expense_listbox.delete(0, tk.END)
        for expense, item, category, date in self.expenses:
            self.expense_listbox.insert(
                tk.END, f"{expense} - {item} - {category} ({date})"
            ) 

För att kunna förfina den angivna texten behöver jag mer sammanhang om vad du vill att jag ska göra med detta kodavsnitt. Här är dock mitt försök att få den givna texten att låta mer sofistikerad:pythondef update_total_label(utgifter):total = sum(utgifter)return totaldef save_expenses(filename=“utgifter.csv”, utgifter=Ingen):if not utgifter:utgifter = []# Öppna den angivna CSV-filen eller skapa en om den inte finnstry:with open(filename, “w”) as f:writer = csv.writer(f)# Skriv rubriken rowwriter.writerow([…])

     def update_total_label(self):
        total_expenses = sum(float(expense[0]) for expense in self.expenses)
        self.total_label.config(text=f"Total Expenses: USD {total_expenses:.2f}")

    def save_expenses(self):
        with open("expenses.csv", "w", newline="") as csvfile:
            writer = csv.writer(csvfile)
            column_headers = ["Expense Amount", "Item Description", "Category", "Date"]
            writer.writerow(column_headers)
            for expense in self.expenses:
                writer.writerow(expense)) 

För att visualisera fördelningen av månatliga utgifter över olika kategorier kan vi implementera en metod som heter show_expenses_chart som tar utgifter listan som indata. Låt oss först definiera en ordbok med namnet category_totals , som kommer att fungera som en räknare för att ackumulera de totala utgifterna för varje utgiftskategori. Vi itererar över posterna i listan expenses och konverterar varje utgiftsbelopp från sträng till float.För varje kategori, om den finns i category_totals ordboken, lägger vi till dess nyckelvärde till den befintliga totalen, annars skapar vi ett nytt nyckel-värdepar som representerar det aktuella utgiftsbeloppet.

     def show_expenses_chart(self):
        category_totals = {}
        for expense, _, category, _ in self.expenses:
            try:
                amount = float(expense)
            except ValueError:
                continue
            category_totals[category] = category_totals.get(category, 0) \\+ amount 

För att skapa en visuell representation av den kategoriska fördelningen av utgifter i ett dataset kan man använda matplotlibs funktion pie . Denna funktion gör det möjligt att generera ett cirkeldiagram baserat på de givna utgiftsbeloppen och deras motsvarande kategorier. Genom att ställa in olika parametrar som autopct , equal och diagrammets titel kan användarna anpassa hur slutresultatet visas.

         categories = list(category_totals.keys())
        expenses = list(category_totals.values())
        plt.figure(figsize=(8, 6))
        plt.pie(
            expenses, labels=categories, autopct="%1.1f%%", startangle=140, shadow=True
        )
        plt.axis("equal")
        plt.title(f"Expense Categories Distribution (USD)")
        plt.show() 

Utnyttja funktionerna i klassen ExpenseTrackerApp genom att instansiera dess instans och därefter aktivera Tkinter-händelseslingan med metoden mainloop(), som upprätthåller en kontinuerlig övervakning av användarinteraktioner tills det grafiska gränssnittet stängs.

 if __name__ == "__main__":
    app = ExpenseTrackerApp()
    app.mainloop() 

Testa olika funktioner i Python Expense Tracker

När programmet körs startas ett grafiskt användargränssnitt (GUI) med inmatningsfält för att registrera relevant information om en utgift, till exempel beskrivning, kategori och datum, samt textrutor för inmatning av numeriska värden. Genom att skriva in denna information och klicka på knappen “Lägg till utgift” kan man förvänta sig att en ny post läggs till i listrutan. Dessutom uppdaterar programmet kontinuerligt den sammanlagda summan av alla registrerade utgifter för din bekvämlighet.

/sv/images/adding-entries-to-expense-tracker.jpg

När du har valt en specifik kostnadspost klickar du på knappen “Redigera kostnader” för att påbörja redigeringsprocessen. Då öppnas en dialogruta där du kan ändra detaljerna för den valda enskilda utgiftsposten inom dess befintliga sammanhang.

/sv/images/selecting-and-editing-expense.jpg

Ta bort en specifik utgiftspost genom att klicka på knappen “Ta bort utgifter”, vilket tar bort den valda posten från listan över utgifter.

/sv/images/selecting-and-deleting-expense.jpg

När du klickar på knappen “Show Expenses Chart” genererar programmet en grafisk representation i form av ett cirkeldiagram som illustrerar fördelningen av utgifterna på olika kategorier, tillsammans med deras respektive namn och procentandelar.

/sv/images/pie-chart-of-expenses.jpg

Förbättra Expense Tracker

För att förbättra användarupplevelsen är det möjligt att integrera en sökfunktion som gör det möjligt för individer att hitta särskilda utgifter enligt deras beskrivning, värde, klassificering eller datum.Dessutom kan du tillhandahålla alternativ för sortering och filtrering av dataposter. Det skulle vara fördelaktigt att anpassa applikationen för att passa olika språk och valutastilar.

Överväg att införliva meddelandefunktionalitet i applikationen, så att användarna kan fastställa tröskelvärden som utlöser varningar när de bryts. Dessa varningar kan fungera som en varning mot överutnyttjande och hjälpa till att identifiera oregelbundna utgifter.