Created
October 28, 2024 12:13
-
-
Save pleabargain/703edfff049974a5c952f939de4e26b9 to your computer and use it in GitHub Desktop.
buy vs rent calculator written in python and tkinter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tkinter as tk | |
from tkinter import ttk, messagebox, filedialog | |
import json | |
from datetime import datetime | |
import numpy as np | |
# Help Documentation | |
HELP_TEXT = """ | |
Buy vs. Rent Calculator | |
====================== | |
Description: | |
----------- | |
This application helps users make informed decisions between buying and renting property by providing | |
comprehensive financial analysis. It considers various factors including purchase costs, monthly expenses, | |
rental costs, and long-term financial implications. | |
Key Features: | |
------------ | |
1. Purchase Analysis: | |
- Calculate mortgage payments based on purchase price, down payment, and interest rate | |
- Include closing costs and initial investment requirements | |
- Multiple down payment scenario analysis | |
2. Monthly Expense Tracking: | |
- Property-related expenses (taxes, insurance, HOA) | |
- Living expenses (food, utilities, gas, miscellaneous) | |
- Maintenance and repair reserves | |
- PMI calculations for down payments < 20% | |
3. Rental Cost Analysis: | |
- Monthly rent calculations | |
- Rental insurance | |
- Utility costs | |
- Total annual rental expenses | |
4. Comparative Analysis: | |
- Long-term cost comparison | |
- Equity building analysis | |
- Property appreciation calculations | |
- Break-even point analysis | |
- Monthly cost differences | |
5. Data Management: | |
- Save analysis to JSON file | |
- Load previous analysis | |
- Multiple scenario comparisons | |
Usage Tips: | |
---------- | |
1. Complete all sections in order: Purchase → Monthly Expenses → Rental → Analysis | |
2. Use realistic appreciation rates based on local market data | |
3. Include all monthly living expenses for accurate comparison | |
4. Consider multiple down payment scenarios | |
5. Save your analysis for future reference | |
Note: All monetary values should be entered as numbers without currency symbols or commas. | |
""" | |
class HousingCalculatorGUI: | |
def __init__(self, root): | |
self.root = root | |
self.root.title("Buy vs. Rent Calculator") | |
self.root.geometry("800x900") | |
# Configure style | |
style = ttk.Style() | |
style.configure('Header.TLabel', font=('Helvetica', 12, 'bold')) | |
# Initialize data dictionary | |
self.data = { | |
'analysis_date': datetime.now().strftime('%Y-%m-%d'), | |
'purchase': {}, | |
'monthly_expenses': {}, | |
'rental': {}, | |
'comparative_analysis': {} | |
} | |
# Create notebook for tabs | |
self.notebook = ttk.Notebook(root) | |
self.notebook.pack(fill='both', expand=True, padx=10, pady=5) | |
# Create tabs | |
self.purchase_tab = ttk.Frame(self.notebook) | |
self.expenses_tab = ttk.Frame(self.notebook) | |
self.rental_tab = ttk.Frame(self.notebook) | |
self.analysis_tab = ttk.Frame(self.notebook) | |
self.notebook.add(self.purchase_tab, text='Purchase Details') | |
self.notebook.add(self.expenses_tab, text='Monthly Expenses') | |
self.notebook.add(self.rental_tab, text='Rental Costs') | |
self.notebook.add(self.analysis_tab, text='Analysis') | |
# Initialize variables | |
self.init_variables() | |
# Create forms | |
self.create_purchase_form() | |
self.create_expenses_form() | |
self.create_rental_form() | |
self.create_analysis_form() | |
# Create menu | |
self.create_menu() | |
def init_variables(self): | |
# Purchase variables | |
self.purchase_price = tk.StringVar(value="500000") | |
self.down_payment_percent = tk.StringVar(value="20") | |
self.interest_rate = tk.StringVar(value="6.5") | |
self.loan_term = tk.StringVar(value="30") | |
self.closing_cost_percent = tk.StringVar(value="3") | |
# Monthly expenses variables | |
self.property_tax_rate = tk.StringVar(value="1.5") | |
self.insurance_rate = tk.StringVar(value="0.5") | |
self.hoa_monthly = tk.StringVar(value="300") | |
self.utilities_monthly_owner = tk.StringVar(value="200") | |
# Rental variables | |
self.monthly_rent = tk.StringVar(value="2500") | |
self.rental_insurance = tk.StringVar(value="20") | |
self.utilities_monthly_renter = tk.StringVar(value="200") | |
# Analysis variables | |
self.appreciation_rate = tk.StringVar(value="3") | |
self.analysis_years = tk.StringVar(value="5") | |
# Add new monthly living expenses | |
self.food_expenses = tk.StringVar(value="600") | |
self.gas_expenses = tk.StringVar(value="200") | |
self.electricity_expenses = tk.StringVar(value="150") | |
self.misc_expenses = tk.StringVar(value="300") | |
# Multiple down payment analysis | |
self.down_payment_1 = tk.StringVar(value="40") | |
self.down_payment_2 = tk.StringVar(value="45") | |
self.down_payment_3 = tk.StringVar(value="50") | |
self.down_payment_4 = tk.StringVar(value="55") | |
self.down_payment_5 = tk.StringVar(value="60") | |
def create_labeled_entry(self, parent, label_text, variable, row, column=0, span=2, prefix="", suffix=""): | |
frame = ttk.Frame(parent) | |
frame.grid(row=row, column=column, columnspan=span, sticky='w', padx=5, pady=2) | |
ttk.Label(frame, text=label_text).pack(side='left') | |
if prefix: | |
ttk.Label(frame, text=prefix).pack(side='left') | |
ttk.Entry(frame, textvariable=variable, width=15).pack(side='left') | |
if suffix: | |
ttk.Label(frame, text=suffix).pack(side='left') | |
return frame | |
def create_purchase_form(self): | |
ttk.Label(self.purchase_tab, text="Purchase Details", font=('Helvetica', 12, 'bold')).grid(row=0, column=0, pady=10) | |
self.create_labeled_entry(self.purchase_tab, "Purchase Price:", self.purchase_price, 1, prefix="$") | |
self.create_labeled_entry(self.purchase_tab, "Down Payment:", self.down_payment_percent, 2, suffix="%") | |
self.create_labeled_entry(self.purchase_tab, "Interest Rate:", self.interest_rate, 3, suffix="%") | |
self.create_labeled_entry(self.purchase_tab, "Loan Term:", self.loan_term, 4, suffix="years") | |
self.create_labeled_entry(self.purchase_tab, "Closing Costs:", self.closing_cost_percent, 5, suffix="%") | |
ttk.Button(self.purchase_tab, text="Calculate Purchase Costs", | |
command=self.calculate_purchase_costs).grid(row=6, column=0, pady=20) | |
self.purchase_result = ttk.Label(self.purchase_tab, text="") | |
self.purchase_result.grid(row=7, column=0, columnspan=2, sticky='w', padx=5) | |
def create_expenses_form(self): | |
ttk.Label(self.expenses_tab, text="Monthly Expenses", font=('Helvetica', 12, 'bold')).grid(row=0, column=0, pady=10) | |
self.create_labeled_entry(self.expenses_tab, "Property Tax Rate:", self.property_tax_rate, 1, suffix="%") | |
self.create_labeled_entry(self.expenses_tab, "Insurance Rate:", self.insurance_rate, 2, suffix="%") | |
self.create_labeled_entry(self.expenses_tab, "HOA Fees:", self.hoa_monthly, 3, prefix="$") | |
self.create_labeled_entry(self.expenses_tab, "Monthly Utilities:", self.utilities_monthly_owner, 4, prefix="$") | |
ttk.Button(self.expenses_tab, text="Calculate Monthly Expenses", | |
command=self.calculate_monthly_expenses).grid(row=5, column=0, pady=20) | |
self.expenses_result = ttk.Label(self.expenses_tab, text="") | |
self.expenses_result.grid(row=6, column=0, columnspan=2, sticky='w', padx=5) | |
self.create_living_expenses_form() | |
# Add a new method for multiple down payment analysis: | |
def create_down_payment_analysis_form(self): | |
frame = ttk.LabelFrame(self.analysis_tab, text="Multiple Down Payment Analysis") | |
frame.grid(row=5, column=0, columnspan=2, sticky='nsew', padx=5, pady=10) | |
self.create_labeled_entry(frame, "Down Payment 1:", self.down_payment_1, 0, suffix="%") | |
self.create_labeled_entry(frame, "Down Payment 2:", self.down_payment_2, 1, suffix="%") | |
self.create_labeled_entry(frame, "Down Payment 3:", self.down_payment_3, 2, suffix="%") | |
self.create_labeled_entry(frame, "Down Payment 4:", self.down_payment_4, 3, suffix="%") | |
self.create_labeled_entry(frame, "Down Payment 5:", self.down_payment_5, 4, suffix="%") | |
ttk.Button(frame, text="Compare Down Payments", | |
command=self.analyze_multiple_down_payments).grid(row=5, column=0, pady=10) | |
# Add method to analyze multiple down payments: | |
def analyze_multiple_down_payments(self): | |
try: | |
if not self.data.get('purchase'): | |
messagebox.showerror("Error", "Please calculate purchase costs first.") | |
return | |
down_payments = [ | |
float(self.down_payment_1.get()), | |
float(self.down_payment_2.get()), | |
float(self.down_payment_3.get()), | |
float(self.down_payment_4.get()), | |
float(self.down_payment_5.get()) | |
] | |
analysis_text = "Multiple Down Payment Analysis:\n" | |
analysis_text += "-" * 50 + "\n\n" | |
for dp in down_payments: | |
# Calculate costs with this down payment | |
purchase_price = float(self.purchase_price.get()) | |
down_payment = purchase_price * (dp / 100) | |
loan_amount = purchase_price - down_payment | |
monthly_payment = self.calculate_mortgage_payment( | |
loan_amount, | |
float(self.interest_rate.get())/100, | |
float(self.loan_term.get()) | |
) | |
# Calculate ROI | |
total_investment = down_payment + float(self.closing_cost_percent.get())/100 * purchase_price | |
monthly_expenses = monthly_payment + sum([ | |
float(self.food_expenses.get()), | |
float(self.gas_expenses.get()), | |
float(self.electricity_expenses.get()), | |
float(self.misc_expenses.get()) | |
]) | |
yearly_expenses = monthly_expenses * 12 | |
appreciation = purchase_price * (float(self.appreciation_rate.get())/100) | |
# First year ROI | |
first_year_roi = ((appreciation - yearly_expenses) / total_investment) * 100 | |
analysis_text += f"Down Payment: {dp}%\n" | |
analysis_text += f"Down Payment Amount: ${down_payment:,.2f}\n" | |
analysis_text += f"Loan Amount: ${loan_amount:,.2f}\n" | |
analysis_text += f"Monthly Payment: ${monthly_payment:,.2f}\n" | |
analysis_text += f"Total Monthly Expenses: ${monthly_expenses:,.2f}\n" | |
analysis_text += f"Total Investment: ${total_investment:,.2f}\n" | |
analysis_text += f"First Year ROI: {first_year_roi:.2f}%\n" | |
analysis_text += "-" * 30 + "\n\n" | |
self.analysis_result.insert(tk.END, "\n" + analysis_text) | |
except ValueError as e: | |
messagebox.showerror("Error", "Please enter valid numbers for all fields.") | |
# Add a new method for creating the living expenses form: | |
def create_living_expenses_form(self): | |
frame = ttk.LabelFrame(self.expenses_tab, text="Monthly Living Expenses") | |
frame.grid(row=7, column=0, columnspan=2, sticky='nsew', padx=5, pady=10) | |
self.create_labeled_entry(frame, "Food:", self.food_expenses, 0, prefix="$") | |
self.create_labeled_entry(frame, "Gas:", self.gas_expenses, 1, prefix="$") | |
self.create_labeled_entry(frame, "Electricity:", self.electricity_expenses, 2, prefix="$") | |
self.create_labeled_entry(frame, "Miscellaneous:", self.misc_expenses, 3, prefix="$") | |
def create_rental_form(self): | |
ttk.Label(self.rental_tab, text="Rental Costs", font=('Helvetica', 12, 'bold')).grid(row=0, column=0, pady=10) | |
self.create_labeled_entry(self.rental_tab, "Monthly Rent:", self.monthly_rent, 1, prefix="$") | |
self.create_labeled_entry(self.rental_tab, "Rental Insurance:", self.rental_insurance, 2, prefix="$") | |
self.create_labeled_entry(self.rental_tab, "Monthly Utilities:", self.utilities_monthly_renter, 3, prefix="$") | |
ttk.Button(self.rental_tab, text="Calculate Rental Costs", | |
command=self.calculate_rental_costs).grid(row=4, column=0, pady=20) | |
self.rental_result = ttk.Label(self.rental_tab, text="") | |
self.rental_result.grid(row=5, column=0, columnspan=2, sticky='w', padx=5) | |
def create_analysis_form(self): | |
ttk.Label(self.analysis_tab, text="Comparative Analysis", | |
style='Header.TLabel').grid(row=0, column=0, pady=10) | |
self.create_labeled_entry(self.analysis_tab, "Appreciation Rate:", | |
self.appreciation_rate, 1, suffix="%") | |
self.create_labeled_entry(self.analysis_tab, "Analysis Period:", | |
self.analysis_years, 2, suffix="years") | |
ttk.Button(self.analysis_tab, text="Run Analysis", | |
command=self.run_comparative_analysis).grid(row=3, column=0, pady=20) | |
# Create Text widget with scrollbar | |
frame = ttk.Frame(self.analysis_tab) | |
frame.grid(row=4, column=0, columnspan=2, sticky='nsew', padx=5) | |
# Add scrollbar | |
scrollbar = ttk.Scrollbar(frame) | |
scrollbar.pack(side=tk.RIGHT, fill=tk.Y) | |
# Create Text widget from tk, not ttk | |
self.analysis_result = tk.Text(frame, height=20, width=70, | |
yscrollcommand=scrollbar.set) | |
self.analysis_result.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) | |
# Configure scrollbar | |
scrollbar.config(command=self.analysis_result.yview) | |
# Configure tag for better formatting | |
self.analysis_result.tag_configure('bold', font=('Helvetica', 10, 'bold')) | |
self.create_down_payment_analysis_form() | |
def create_menu(self): | |
menubar = tk.Menu(self.root) | |
self.root.config(menu=menubar) | |
file_menu = tk.Menu(menubar, tearoff=0) | |
menubar.add_cascade(label="File", menu=file_menu) | |
file_menu.add_command(label="Save Analysis", command=self.save_to_json) | |
file_menu.add_command(label="Load Analysis", command=self.load_from_json) | |
file_menu.add_separator() | |
file_menu.add_command(label="Exit", command=self.root.quit) | |
def calculate_mortgage_payment(self, principal, annual_rate, years): | |
"""Calculate monthly mortgage payment""" | |
r = annual_rate / 12 # Monthly interest rate | |
n = years * 12 # Total number of payments | |
return principal * (r * (1 + r)**n) / ((1 + r)**n - 1) | |
def calculate_purchase_costs(self): | |
try: | |
purchase_price = float(self.purchase_price.get()) | |
down_payment_percent = float(self.down_payment_percent.get()) | |
annual_rate = float(self.interest_rate.get()) | |
loan_years = float(self.loan_term.get()) | |
closing_cost_percent = float(self.closing_cost_percent.get()) | |
down_payment = purchase_price * (down_payment_percent / 100) | |
loan_amount = purchase_price - down_payment | |
closing_costs = purchase_price * (closing_cost_percent / 100) | |
monthly_payment = self.calculate_mortgage_payment(loan_amount, annual_rate/100, loan_years) | |
self.data['purchase'] = { | |
'purchase_price': purchase_price, | |
'down_payment': down_payment, | |
'loan_amount': loan_amount, | |
'annual_interest_rate': annual_rate, | |
'loan_term_years': loan_years, | |
'closing_costs': closing_costs, | |
'monthly_mortgage_payment': monthly_payment, | |
'total_initial_costs': down_payment + closing_costs | |
} | |
result_text = f""" | |
Purchase Summary: | |
---------------- | |
Down Payment: ${down_payment:,.2f} | |
Loan Amount: ${loan_amount:,.2f} | |
Closing Costs: ${closing_costs:,.2f} | |
Monthly Mortgage Payment: ${monthly_payment:,.2f} | |
Total Initial Costs: ${(down_payment + closing_costs):,.2f} | |
""" | |
self.purchase_result.config(text=result_text) | |
except ValueError as e: | |
messagebox.showerror("Error", "Please enter valid numbers for all fields.") | |
def calculate_monthly_expenses(self): | |
try: | |
if not self.data.get('purchase'): | |
messagebox.showerror("Error", "Please calculate purchase costs first.") | |
return | |
purchase_price = self.data['purchase']['purchase_price'] | |
down_payment = self.data['purchase']['down_payment'] | |
property_tax_rate = float(self.property_tax_rate.get()) | |
insurance_rate = float(self.insurance_rate.get()) | |
hoa_monthly = float(self.hoa_monthly.get()) | |
utilities_monthly = float(self.utilities_monthly_owner.get()) | |
# Get monthly living expenses | |
monthly_living_expenses = sum([ | |
float(self.food_expenses.get()), | |
float(self.gas_expenses.get()), | |
float(self.electricity_expenses.get()), | |
float(self.misc_expenses.get()) | |
]) | |
# Calculate PMI if down payment is less than 20% | |
pmi = (purchase_price - down_payment) * 0.01 / 12 if down_payment/purchase_price < 0.2 else 0 | |
# Update monthly expenses dictionary to include living expenses | |
self.data['monthly_expenses'] = { | |
'mortgage_payment': self.data['purchase']['monthly_mortgage_payment'], | |
'property_tax': (purchase_price * property_tax_rate/100) / 12, | |
'insurance': (purchase_price * insurance_rate/100) / 12, | |
'hoa_fees': hoa_monthly, | |
'pmi': pmi, | |
'utilities': utilities_monthly, | |
'maintenance_reserve': (purchase_price * 0.01) / 12, | |
'repair_reserve': (purchase_price * 0.005) / 12, | |
'living_expenses': monthly_living_expenses # Add living expenses | |
} | |
# Calculate total including all expenses | |
total_monthly = sum(self.data['monthly_expenses'].values()) | |
result_text = f""" | |
Monthly Expenses Summary: | |
---------------------- | |
Mortgage Payment: ${self.data['monthly_expenses']['mortgage_payment']:,.2f} | |
Property Tax: ${self.data['monthly_expenses']['property_tax']:,.2f} | |
Insurance: ${self.data['monthly_expenses']['insurance']:,.2f} | |
HOA Fees: ${hoa_monthly:,.2f} | |
PMI: ${pmi:,.2f} | |
Utilities: ${utilities_monthly:,.2f} | |
Maintenance Reserve: ${self.data['monthly_expenses']['maintenance_reserve']:,.2f} | |
Repair Reserve: ${self.data['monthly_expenses']['repair_reserve']:,.2f} | |
Living Expenses: ${monthly_living_expenses:,.2f} | |
Total Monthly: ${total_monthly:,.2f} | |
""" | |
self.expenses_result.config(text=result_text) | |
except ValueError as e: | |
messagebox.showerror("Error", "Please enter valid numbers for all fields.") | |
def calculate_rental_costs(self): | |
try: | |
monthly_rent = float(self.monthly_rent.get()) | |
insurance = float(self.rental_insurance.get()) | |
utilities = float(self.utilities_monthly_renter.get()) | |
total_monthly = monthly_rent + insurance + utilities | |
self.data['rental'] = { | |
'monthly_rent': monthly_rent, | |
'insurance': insurance, | |
'utilities': utilities, | |
'total_monthly': total_monthly, | |
'total_annual': total_monthly * 12 | |
} | |
result_text = f""" | |
Rental Costs Summary: | |
------------------- | |
Monthly Rent: ${monthly_rent:,.2f} | |
Insurance: ${insurance:,.2f} | |
Utilities: ${utilities:,.2f} | |
Total Monthly: ${total_monthly:,.2f} | |
Total Annual: ${(total_monthly * 12):,.2f} | |
""" | |
self.rental_result.config(text=result_text) | |
except ValueError as e: | |
messagebox.showerror("Error", "Please enter valid numbers for all fields.") | |
def run_comparative_analysis(self): | |
try: | |
if not all([self.data.get('purchase'), self.data.get('monthly_expenses'), self.data.get('rental')]): | |
messagebox.showerror("Error", "Please calculate all costs first.") | |
return | |
appreciation_rate = float(self.appreciation_rate.get()) | |
years = float(self.analysis_years.get()) | |
purchase_price = self.data['purchase']['purchase_price'] | |
loan_amount = self.data['purchase']['loan_amount'] | |
annual_rate = self.data['purchase']['annual_interest_rate'] | |
# Calculate equity building through principal payments | |
monthly_rate = annual_rate / (100 * 12) | |
loan_months = self.data['purchase']['loan_term_years'] * 12 | |
principal_payment = loan_amount * (monthly_rate * (1 + monthly_rate)**loan_months) / \ | |
((1 + monthly_rate)**loan_months - 1) - loan_amount * monthly_rate | |
# Add living expenses to monthly costs | |
monthly_living_expenses = sum([ | |
float(self.food_expenses.get()), | |
float(self.gas_expenses.get()), | |
float(self.electricity_expenses.get()), | |
float(self.misc_expenses.get()) | |
]) | |
buying_total_costs = (sum(self.data['monthly_expenses'].values()) + monthly_living_expenses) * 12 * years | |
rental_total_costs = (self.data['rental']['total_monthly'] + monthly_living_expenses) * 12 * years | |
buying_total_costs = sum(self.data['monthly_expenses'].values()) * 12 * years | |
rental_total_costs = self.data['rental']['total_monthly'] * 12 * years | |
equity_built = principal_payment * 12 * years | |
appreciation = purchase_price * (((1 + appreciation_rate/100)**years) - 1) | |
buying_net = equity_built + appreciation - buying_total_costs | |
renting_net = -rental_total_costs | |
self.data['comparative_analysis'] = { | |
'years_analyzed': years, | |
'appreciation_rate': appreciation_rate, | |
'buying': { | |
'total_costs': buying_total_costs, | |
'equity_built': equity_built, | |
'appreciation': appreciation, | |
'net_position': buying_net | |
}, | |
'renting': { | |
'total_costs': rental_total_costs, | |
'equity_built': 0, | |
'appreciation': 0, | |
'net_position': renting_net | |
}, | |
'net_difference': buying_net - renting_net | |
} | |
analysis_text = f""" | |
Comparative Analysis Summary ({years} Years): | |
---------------------------------------- | |
BUYING: | |
Total Costs: ${buying_total_costs:,.2f} | |
Equity Built: ${equity_built:,.2f} | |
Property Appreciation: ${appreciation:,.2f} | |
Net Position: ${buying_net:,.2f} | |
RENTING: | |
Total Costs: ${rental_total_costs:,.2f} | |
Equity Built: $0.00 | |
Property Appreciation: $0.00 | |
Net Position: ${renting_net:,.2f} | |
COMPARISON: | |
Net Difference (Buying vs Renting): ${(buying_net - renting_net):,.2f} | |
Monthly Comparison: | |
----------------- | |
Monthly Cost of Buying: ${(sum(self.data['monthly_expenses'].values())):,.2f} | |
Monthly Cost of Renting: ${self.data['rental']['total_monthly']:,.2f} | |
Monthly Difference: ${(sum(self.data['monthly_expenses'].values()) - self.data['rental']['total_monthly']):,.2f} | |
Break-Even Analysis: | |
------------------ | |
Years to Break Even: {abs(buying_total_costs/(buying_net - renting_net)):,.1f} | |
Additional Insights: | |
----------------- | |
• The buying scenario {' is ' if buying_net > renting_net else ' is not '} financially advantageous over {years} years | |
• Property appreciation accounts for ${appreciation:,.2f} of the buying benefit | |
• Monthly ownership costs are ${abs(sum(self.data['monthly_expenses'].values()) - self.data['rental']['total_monthly']):,.2f} {'higher' if sum(self.data['monthly_expenses'].values()) > self.data['rental']['total_monthly'] else 'lower'} than renting | |
""" | |
self.analysis_result.delete(1.0, tk.END) | |
self.analysis_result.insert(tk.END, analysis_text) | |
except ValueError as e: | |
messagebox.showerror("Error", "Please enter valid numbers for all fields.") | |
except ZeroDivisionError: | |
messagebox.showerror("Error", "Cannot calculate break-even point - costs are equal.") | |
def save_to_json(self): | |
try: | |
filename = tk.filedialog.asksaveasfilename( | |
defaultextension=".json", | |
filetypes=[("JSON files", "*.json"), ("All files", "*.*")], | |
title="Save Analysis As" | |
) | |
if filename: | |
with open(filename, 'w') as f: | |
json.dump(self.data, f, indent=4) | |
messagebox.showinfo("Success", "Analysis saved successfully!") | |
except Exception as e: | |
messagebox.showerror("Error", f"Error saving file: {str(e)}") | |
def load_from_json(self): | |
try: | |
filename = tk.filedialog.askopenfilename( | |
filetypes=[("JSON files", "*.json"), ("All files", "*.*")], | |
title="Load Analysis" | |
) | |
if filename: | |
with open(filename, 'r') as f: | |
self.data = json.load(f) | |
self.update_forms_from_data() | |
messagebox.showinfo("Success", "Analysis loaded successfully!") | |
except Exception as e: | |
messagebox.showerror("Error", f"Error loading file: {str(e)}") | |
def update_forms_from_data(self): | |
"""Update all form fields from loaded data""" | |
if 'purchase' in self.data: | |
self.purchase_price.set(str(self.data['purchase']['purchase_price'])) | |
self.down_payment_percent.set(str(self.data['purchase']['down_payment'] / | |
self.data['purchase']['purchase_price'] * 100)) | |
self.interest_rate.set(str(self.data['purchase']['annual_interest_rate'])) | |
self.loan_term.set(str(self.data['purchase']['loan_term_years'])) | |
self.calculate_purchase_costs() | |
if 'monthly_expenses' in self.data: | |
self.property_tax_rate.set(str(self.data['monthly_expenses']['property_tax'] * 12 / | |
self.data['purchase']['purchase_price'] * 100)) | |
self.insurance_rate.set(str(self.data['monthly_expenses']['insurance'] * 12 / | |
self.data['purchase']['purchase_price'] * 100)) | |
self.hoa_monthly.set(str(self.data['monthly_expenses']['hoa_fees'])) | |
self.utilities_monthly_owner.set(str(self.data['monthly_expenses']['utilities'])) | |
self.calculate_monthly_expenses() | |
if 'rental' in self.data: | |
self.monthly_rent.set(str(self.data['rental']['monthly_rent'])) | |
self.rental_insurance.set(str(self.data['rental']['insurance'])) | |
self.utilities_monthly_renter.set(str(self.data['rental']['utilities'])) | |
self.calculate_rental_costs() | |
if 'comparative_analysis' in self.data: | |
self.appreciation_rate.set(str(self.data['comparative_analysis']['appreciation_rate'])) | |
self.analysis_years.set(str(self.data['comparative_analysis']['years_analyzed'])) | |
self.run_comparative_analysis() | |
def main(): | |
root = tk.Tk() | |
app = HousingCalculatorGUI(root) | |
root.mainloop() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment