0

I am having issues with my program. It is supposed to collect information and make calculations but not until the command button is clicked. However, the program is acting like the button is being clicked as soon as the program starts running and then freezes. I am kind of stuck as it seems like the more that I add, the worse things get. Can anybody please tell me what I might be doing wrong.

import tkinter as tk
from tkinter import messagebox

# Create the main window
window = tk.Tk()
window.title("Walkerton Water and Sewage")
window.geometry("700x500")
window.columnconfigure(0, weight=2)
window.columnconfigure(1, weight=1)
window.columnconfigure(2, weight=1)

# Create the input frame for customer information
customer_info_frame = tk.LabelFrame(window, text="Customer Information")
customer_info_frame.grid(row=0, column=0, padx=3, pady=3, sticky=tk.NW)

# Create the input frame for meter readings
meter_reading_frame = tk.LabelFrame(window, text="Meter Readings")
meter_reading_frame.grid(row=0, column=1, padx=3, pady=3, sticky=tk.NW)

# Create the sewer usage frame
sewer_usage_frame = tk.LabelFrame(window, text="Sewer Usage")
sewer_usage_frame.grid(row=0, column=2, padx=3, pady=3, sticky=tk.NW)

# Create the service options frame
service_type_frame = tk.LabelFrame(window, text="Service Type")
service_type_frame.grid(row=0, column=0, columnspan=3, padx=3, pady=115, sticky=tk.NW)

bill_summary_frame = tk.LabelFrame(window, text="Bill Summary")
bill_summary_frame.grid(row=0, column=0, columnspan=4, padx=145, pady=105, sticky=tk.NW)

# Create labels and entry fields for customer information
tk.Label(customer_info_frame, text="Name:").grid(row=0, column=0, sticky=tk.W)
name_entry = tk.Entry(customer_info_frame, width=10)
name_entry.grid(row=0, column=1)

tk.Label(customer_info_frame, text="Address:").grid(row=1, column=0, sticky=tk.W)
address_entry = tk.Entry(customer_info_frame)
address_entry.grid(row=1, column=1)

tk.Label(customer_info_frame, text="Province:").grid(row=2, column=0, sticky=tk.W)
province_entry = tk.Entry(customer_info_frame)
province_entry.grid(row=2, column=1)

tk.Label(customer_info_frame, text="Postal Code:").grid(row=3, column=0, sticky=tk.W)
postal_code_entry = tk.Entry(customer_info_frame)
postal_code_entry.grid(row=3, column=1)

# Create labels and entry fields for meter readings
tk.Label(meter_reading_frame, text="Previous Reading:").grid(row=0, column=0, sticky=tk.W)
previous_reading_entry = tk.Entry(meter_reading_frame)
previous_reading_entry.grid(row=0, column=1)

tk.Label(meter_reading_frame, text="Current Reading:").grid(row=1, column=0, sticky=tk.W)
current_reading_entry = tk.Entry(meter_reading_frame)
current_reading_entry.grid(row=1, column=1)

tk.Label(meter_reading_frame, text="Litres Used:").grid(row=2, column=0, sticky=tk.W)
litres_used = tk.Entry(meter_reading_frame, state="readonly")
litres_used.grid(row=2, column=1)

# Variable identification
def get_customer_name():
    return name_entry.get()

def get_customer_address():
    return address_entry.get()

def get_customer_province():
    return province_entry.get()

def get_customer_postal_code():
    return postal_code_entry.get()

def get_previous_meter_reading():
    return previous_reading_entry.get()

def get_current_meter_reading():
    return current_reading_entry.get()

def calculate_bill():
    print("Hello")
    # Check if all required fields are filled
    if not name_entry.get() or not address_entry.get() or not province_entry.get()   or not postal_code_entry.get() or not previous_reading_entry.get() or not current_reading_entry.get():
        messagebox.showerror("Error", "Please fill in all required fields.")
        return

    # Check if a service type is selected
    if not water_only_checkbox.get() and not sewer_and_water_checkbox.get():
          messagebox.showerror("Error", "Please select a service type.")
          return

    # Check if current meter reading exceeds previous meter reading
    if int(current_reading_entry.get()) <= int(previous_reading_entry.get()):
        previous_reading_entry.set("")
        current_reading_entry.set("")
        messagebox.showerror("Error", "Current meter reading must be greater than previous meter reading.")
        return

 # Get the values entered by the user
    previous_reading = float(previous_reading_entry.get())
    current_reading = float(current_reading_entry.get())
    litres_used = current_reading - previous_reading
  
    # Get the water usage from the entry field
    water_usage_entry = int(litres_used_entry.get())

    # Calculate water rate based on sliding scale
    if water_usage_entry <= 10000:
      water_rate_entry = 3.50
    elif water_usage_entry <= 20000:
      water_rate_entry = 3.25
    elif water_usage_entry <= 50000:
      water_rate_entry = 3.05
    else:
      water_rate_entry = 2.90

    # Create an entry widget for water rate
    water_rate_entry = tk.Entry(bill_summary_frame, width=5).grid(row=2, column=0, padx=90, pady=2, sticky=tk.W)
    water_rate_entry.grid(row=2, column=0)

        
    # Calculate water service charge based on water usage and type of service
    service_charge_water_entry = 7.50 if water_usage_entry <= 50000 else 6.50
    
    # If both sewer and water service, reduce water service charge by $1
    if litres_used.get():
      service_charge_water_entry -= 1.00
    
    # Calculate total in the water area
    water_total = (water_usage_entry * water_rate_entry / 1000) + service_charge_water_entry
    
    # Display the calculated values in the entry fields
    water_rate_entry.set(f"${water_rate_entry:.2f}")

    service_charge_water_entry.delete(0, tk.END)
    service_charge_water_entry.insert(tk.END, f"${service_charge_water_entry:.2f}")
    
    total_water_entry.delete(0, tk.END)
    total_water_entry.insert(tk.END, f"${water_total:.2f}")
    
    # Calculate sewer rate based on sewer usage
    sewer_usage = int(litres_used.get())
    sewer_rate = 1.25 if sewer_usage < 50000 else 1.15
    
    # Calculate sewer service charge based on sewer usage
    sewer_service_charge = 12.50 if sewer_usage < 50000 else 10.50
    
    # Calculate total in the sewer area
    sewer_total = (sewer_usage * sewer_rate / 1000) + sewer_service_charge
    
    # Display the calculated values in the entry fields
    sewer_rate_entry.delete(0, tk.END)
    sewer_rate_entry.insert(tk.END, f"${sewer_rate:.2f}")
    
    sewer_service_charge.delete(0, tk.END)
    sewer_service_charge.insert(tk.END,f"${sewer_service_charge:.2f}")
    
    total_sewer_entry.delete(0, tk.END)
    total_sewer_entry.insert(tk.END, f"${sewer_total:.2f}")
    
    # Calculate and display the grand total
    grand_total = total_water_entry + total_sewer_entry
    grand_total_entry.delete(0, tk.END)
    grand_total_entry.insert(tk.END, f"${grand_total:.2f}")

# Create the calculate button
calculate_button = tk.Button(window, text="Calculate Bill", command=calculate_bill())
calculate_button.grid(row=0, column=0, padx=10, pady=90, sticky=tk.W)


# Create labels and entry fields for customer information
tk.Label(customer_info_frame, text="Name:").grid(row=0, column=0, sticky=tk.W)
name_entry = tk.Entry(customer_info_frame, width=10)
name_entry.grid(row=0, column=1)

tk.Label(customer_info_frame, text="Address:").grid(row=1, column=0, sticky=tk.W)
address_entry = tk.Entry(customer_info_frame)
address_entry.grid(row=1, column=1)

tk.Label(customer_info_frame, text="Province:").grid(row=2, column=0, sticky=tk.W)
province_entry = tk.Entry(customer_info_frame)
province_entry.grid(row=2, column=1)

tk.Label(customer_info_frame, text="Postal Code:").grid(row=3, column=0, sticky=tk.W)
postal_code_entry = tk.Entry(customer_info_frame)
postal_code_entry.grid(row=3, column=1)

# Create labels and entry fields for meter readings
tk.Label(meter_reading_frame, text="Previous Reading:").grid(row=0, column=0, sticky=tk.W)
previous_reading_entry = tk.Entry(meter_reading_frame)
previous_reading_entry.grid(row=0, column=1)

tk.Label(meter_reading_frame, text="Current Reading:").grid(row=1, column=0, sticky=tk.W)
current_reading_entry = tk.Entry(meter_reading_frame)
current_reading_entry.grid(row=1, column=1)

tk.Label(meter_reading_frame, text="Litres Used:").grid(row=2, column=0, sticky=tk.W)
litres_used = tk.Entry(meter_reading_frame, state="readonly")
litres_used.grid(row=2, column=1)

# Create labels and entry fields for sewer usage
tk.Label(sewer_usage_frame, text="Litres Used:").grid(row=0, column=0, sticky=tk.W)
litres_used_entry = tk.Entry(sewer_usage_frame, state="readonly")
litres_used_entry.grid(row=0, column=1)

tk.Label(sewer_usage_frame, text="Discount Amount:").grid(row=1, column=0, sticky=tk.W)
discount_amount_entry = tk.Entry(sewer_usage_frame, state="readonly")
discount_amount_entry.grid(row=1, column=1)

tk.Label(sewer_usage_frame, text="Billable Amount:").grid(row=2, column=0, sticky=tk.W)
billable_amount_entry = tk.Entry(sewer_usage_frame, state="readonly")
billable_amount_entry.grid(row=2, column=1)

tk.Label(bill_summary_frame, text="Water Charges").grid(row=0, column=0, sticky=tk.W)

tk.Label(bill_summary_frame, text="Water Usage:").grid(row=1, column=0, sticky=tk.W)
water_usage_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
water_usage_entry.grid(row=1, column=0, padx=95)

tk.Label(bill_summary_frame, text="Water Rate:").grid(row=2, column=0, sticky=tk.W)
water_rate_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
water_rate_entry.grid(row=2, column=0, padx=95)

tk.Label(bill_summary_frame, text="Service Charge:").grid(row=3, column=0, sticky=tk.W)
service_charge_water_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
service_charge_water_entry.grid(row=3, column=0, padx=95)

tk.Label(bill_summary_frame, text="Total:").grid(row=4, column=0, sticky=tk.W)
total_water_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
total_water_entry.grid(row=4, column=0, padx=95)

tk.Label(bill_summary_frame, text="Sewer Charges").grid(row=0, column=1, sticky=tk.W)

tk.Label(bill_summary_frame, text="Sewer Usage:").grid(row=1, column=1, sticky=tk.W)
sewer_usage_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
sewer_usage_entry.grid(row=1, column=1, padx=95)

tk.Label(bill_summary_frame, text="Sewer Rate:").grid(row=2, column=1, sticky=tk.W)
sewer_rate_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
sewer_rate_entry.grid(row=2, column=1, padx=95)

tk.Label(bill_summary_frame, text="Service Charge:").grid(row=3, column=1, sticky=tk.W)
service_charge_sewer_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
service_charge_sewer_entry.grid(row=3, column=1, padx=95)

tk.Label(bill_summary_frame, text="Total:").grid(row=4, column=1, sticky=tk.W)
total_sewer_entry = tk.Entry(bill_summary_frame, state="readonly", width=10)
total_sewer_entry.grid(row=4, column=1, padx=95)

tk.Label(bill_summary_frame, text="Grand Total:").grid(row=5, column=0, sticky=tk.W)
grand_total_entry = tk.Entry(bill_summary_frame, state="readonly", width=15)
grand_total_entry.grid(row=5, column=0)

# Create labels and entry fields for service options
water_only_checkbox = tk.Checkbutton(service_type_frame, text="Water Only")
water_only_checkbox.grid(row=0, column=1, sticky=tk.W)

sewer_and_water_checkbox = tk.Checkbutton(service_type_frame, text="Sewer and Water")
sewer_and_water_checkbox.grid(row=1, column=1, sticky=tk.W)

# Calculate the billable amount
#def calculate_billable_amount():
    #previous_reading = float(get_previous_meter_reading())
    #current_reading = float(get_current_meter_reading())
   # litres_used = current_reading - previous_reading

    #discount_amount = float(get_discount_amount())
   # billable_amount = litres_used - discount_amount

    #messagebox.showinfo("Billable Amount", f"The billable amount is {billable_amount:.2f} litres.")


# Run the main window loop
window.mainloop()

shodai
  • 25
  • 4

4 Answers4

3

Change

calculate_button = tk.Button(window, text="Calculate Bill", command=calculate_bill())

To

calculate_button = tk.Button(window, text="Calculate Bill", command=calculate_bill)
Pragmatic_Lee
  • 473
  • 1
  • 4
  • 10
3

When you pass a function as a parameter in Python you shouldn't use the parentheses (unless you want the function to be invoked right away), just the function name:

calculate_button = tk.Button(window, text="Calculate Bill", command=calculate_bill())

should be

calculate_button = tk.Button(window, text="Calculate Bill", command=calculate_bill)

If you need to pass in arguments, say, then you'll need to pass those in in another parameter. Check the Tkinter docs for their preferred method of doing this.

Mr. Tea
  • 66
  • 3
0

On your command=calculate_bill(), remove the parentheses, it should be only command=calculate_bill. If you need to pass a value to the calculate_bill function, use command=lambda: calculate_bill(value).

Also when you post your code for others to read, try to remove everything that you think are unnecessary for the readers, your code has so much stuff that it took quite a while to look for your Button() atleast on mobile, but no worries. Happy coding :)

Loss1
  • 35
  • 3
0

When you pass in command=calculate_bill() as an argument, the code first executes the function itself, then grabs the return value of said function and passes that as an argument. We don't want to pass the outcome of a function, but the function itself. To do that, you just need to pass in command=calculate_bill, without parenthesis.

calculate_button = tk.Button(window, text="Calculate Bill", command=calculate_bill)

Ps. Overcommenting is never good :)

Miodek
  • 48
  • 4