1

So the issue is when I click the calc_button, which calls the calculate_tip method, I get a NameError saying 'subtotal_entry' is not defined. I have tried a bunch of different things to get this working but nothing has worked so far. I am trying to get the users input from the Entry I created called subtotal_entry.

Here is my code:

from tkinter import *
from tkinter import messagebox

class TipGUI:

    def __init__(self,master):
        self.master = master
        master.title('Tip Calculator')

        #create the frames
        subtotal_frame = Frame(master).grid(row=0, column=0)
        percent_frame = Frame(master).grid(row=1, column=0)
        tip_frame = Frame(master).grid(row=2, column=0)
        button_frame = Frame(master).grid(row=3, column=0)
        total_frame = Frame(master).grid(row=4, column=0)

        #create the labels
        subtotal_label = Label(subtotal_frame, text="Enter the amount of the ticket:").grid(row=0, column=0)
        percent_label = Label(percent_frame, text="Enter the tip as a percent:").grid(row=1, column=0)
        tip_label = Label(tip_frame, text="Tip Amount: $").grid(row=2, column=0)
        tipAmt_label = Label(tip_frame, text="").grid(row=2, column=1)
        total_label = Label(total_frame, text="Total Amount: $").grid(row=3, column=0)
        totalAmt_label = Label(total_frame, text="").grid(row=3, column=1)

        #create entry boxes
        subtotal_entry = Entry(subtotal_frame).grid(row=0, column=1)
        percent_entry = Entry(percent_frame).grid(row=1, column=1)

        #create buttons
        calc_button = Button(button_frame, text="Calculate", command= self.calculate_tip).grid(row=4, column=0)
        exit_button = Button(button_frame, text="exit", command= master.quit).grid(row=4, column=1)

    def calculate_tip(self):
        subtotal = Entry.get(subtotal_entry)
        percent = percent_entry.get()

        if subtotal <= 0:
            messagebox.showinfo("Error","Please enter a subtotal greater than 0")
            
        if percent <= 0:
            messagebox.showinfo("Error","Please enter a tip percentage greater than 0")
            
        else:
            tip = subtotal * percent
            total = tip + subtotal

            tipAmt_label.config(text = format(tip, ',.2f'))
            totalAmt_label.config(text = format(total, ',.2f'))

            subtotal_entry.delete(0, END)
            percent_entry.delete(0,END)


#Create the window
window = Tk()
tipGUI = TipGUI(window)
window.mainloop()
  • 2
    `subtotal_entry` is a local variable. It shouldn't be. – Bryan Oakley Dec 15 '21 at 00:57
  • 1
    Other than the scope issue, you have the common issue: [tkinter-attributeerror-nonetype-object-has-no-attribute-attribute-name](https://stackoverflow.com/questions/1101750/tkinter-attributeerror-nonetype-object-has-no-attribute-attribute-name) – acw1668 Dec 15 '21 at 01:03
  • 1
    `subtotal_entry` should be an instance attribute of your `TipGUI` class. i.e. `self.subtotal_entry`. – martineau Dec 15 '21 at 01:06

1 Answers1

0

You have few common problems.

  1. subtotal_entry is local variable which can't be accessed in other functions. You have to use self.subtotal_entry to create variable which can be accessed in other functions in class.

  2. variable = Widget.grid() assigns None to variable because grid(), pack(), place() returns None. You have to do it in two steps

    variable = Widget()
    variable.grid()
    

    And if later you don't have to access some widget (some Labels) then you can skip variable

    Widget().grid()
    
  3. To get value you need subtotal_entry.get() instead of Entry.get(subtotal_entry)

  4. Entry gives string so you have to use int() or float() to convert string to value.


Full working code.

I assumed that percent will be value 0 ... 100, not 0.00 ... 1.00

I removed most of Frames because they were useless.

import tkinter as tk  # PEP8: `import *` is not preferred
from tkinter import messagebox

class TipGUI:

    def __init__(self, master):
        self.master = master
        master.title('Tip Calculator')

        #create the labels
        subtotal_label = tk.Label(master, text="Enter the amount of the ticket:")
        subtotal_label.grid(row=0, column=0, stick='e')
        
        percent_label = tk.Label(master, text="Enter the tip as a percent:")
        percent_label.grid(row=1, column=0, stick='e')
        
        self.tip_label = tk.Label(master, text="Tip Amount: $")
        self.tip_label.grid(row=2, column=0, columnspan=2)
        
        self.total_label = tk.Label(master, text="Total Amount: $")
        self.total_label.grid(row=3, column=0, columnspan=2)

        #create entry boxes
        self.subtotal_entry = tk.Entry(master)
        self.subtotal_entry.grid(row=0, column=1)
        
        self.percent_entry = tk.Entry(master)
        self.percent_entry.grid(row=1, column=1)

        #create buttons
        frame_buttons = tk.Frame(master)
        frame_buttons.grid(row=4, column=0, columnspan=2)
        
        calc_button = tk.Button(frame_buttons, text="Calculate", command=self.calculate_tip)
        calc_button.grid(row=0, column=0)
        exit_button = tk.Button(frame_buttons, text="Exit", command=master.quit)
        exit_button.grid(row=0, column=1)

    def calculate_tip(self):
        subtotal = float(self.subtotal_entry.get())
        percent = float(self.percent_entry.get()) / 100

        if subtotal <= 0:
            messagebox.showinfo("Error","Please enter a subtotal greater than 0")
            
        if percent <= 0:
            messagebox.showinfo("Error","Please enter a tip percentage greater than 0")
            
        else:
            tip = subtotal * percent
            total = tip + subtotal

            self.tip_label.config(text=f"Tip Amount: ${tip:,.2f}")
            self.total_label.config(text=f"Total Amount: ${total:,.2f}")

            self.subtotal_entry.delete(0, 'end')
            self.percent_entry.delete(0, 'end')

#Create the window
window = tk.Tk()
tipGUI = TipGUI(window)
window.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148