0

PYTHON Tkinter buttons which call a function.

I have a function run from a main menu which creates a data entry form for payroll.

I have a button on that form which takes the gross pay figure from the payroll form and passes it into a function to work out deductions like tax, pension etc and ultimately net pay. This deductions and net pay then need to be displayed on the form, bit like a wage slip.

I can pass the multiple values back ok but how can I get those separate values populated onto the form in the correct fields? I am a novice programmer.

def openWagesWindow():
    WagesWindow=tk.Tk()
    WagesWindow.title("Wages")
    WagesWindow.geometry("800x600")
    windowlabel = tk.Label(WagesWindow, text ="Payroll")
                windowlabel.pack()
                
    Grosslabel = tk.Label(WagesWindow, text= 'Gross Pay')
    Grosslabel.pack()
    Grossentry = tk.Entry(WagesWindow)
    Grossentry.insert(0,int(0))
    Grossentry.pack()

    TaxLabel = tk.Label(WagesWindow, text= 'Tax')
    TaxLabel.pack()
    Taxentry = tk.Entry(WagesWindow)
    Taxentry.pack()

    NILabel = tk.Label(WagesWindow, text= 'National Insurance')
    NILabel.pack()
    NIentry = tk.Entry(WagesWindow)
    NIentry.pack()

    PensionLabel = tk.Label(WagesWindow, text= 'Pension')
    PensionLabel.pack()
    Pensionentry = tk.Entry(WagesWindow)
    Pensionentry.pack()

    Deductlabel = tk.Label(WagesWindow, text= 'Deductions')
    Deductlabel.pack()
    Deductentry = tk.Entry(WagesWindow)
    Deductentry.pack()

    NetPaylabel = tk.Label(WagesWindow, text= 'Net Pay')
    NetPaylabel.pack()
    NetPayentry = tk.Entry(WagesWindow)
    NetPayentry.pack()

    backbutton = tk.Button(WagesWindow, text= "Back", command= WagesWindow.destroy)
    backbutton.place(x=350, y=350)
        
    calcbutton = tk.Button(WagesWindow, text= "Calculate", 
      command = lambda:CalcWages(Grossentry.get()))
    calcbutton.place(x=400, y=350)
    calcbutton = tk.Button(WagesWindow, text= "Calculate", 
    command = lambda:CalcWages(Grossentry.get())) 

def CalcWages(Grosspay):
   GP = int(Grosspay) 
   TX = GP *0.2 
   NI = GP *0.14 
   PNS = GP * 0.08 
   DEDUCT= TX+NI+PNS 
   NET= GP-DEDUCT 
   return[TX,NI,PNS,DEDUCT,NET]

1 Answers1

1

So you have a couple questions wrapped up in this. The first one is how to deal with "multiple returns" as a function can return some kind of iterable data structure with multiple values like yours does. Typically, these things are returned in a tuple (not a list) because it is fixed size, immutable, etc. So you can catch multiple returns either individually or with one variable and split it up. Note that in several spots here, the parens for the tuple are optional

Example:

# multiple return

nums = [9, -1, 3, 4, 12, 44, -8, 10]

def max_min(number_list):
    """return a tuple of the max and min values from a collection of numbers"""
    max_value = max(number_list)
    min_value = min(number_list)
    return min_value, max_value

# example 1: catch both max and min in 2 variables
nums_min, nums_max = max_min(nums)
print(f'the min is {nums_min} and the max is {nums_max}')

# example 2: maybe I just want the max.  an underscore is a legal variable name
#            and usually indicates to the reader that it is a "throw-away"
_, nums_max = max_min(nums)
print(f'the max value is {nums_max}')

# example 3:  catch the tuple as a tuple and split it up...
results = max_min(nums)
print(f'the min is {results[0]} and the max is {results[1]}')

Output:

the min is -8 and the max is 44
the max value is 44
the min is -8 and the max is 44

On to the tkinter.... You can employ the strategy above to catch the multiple outputs and update the windows. You could have done what I'm doing below in 1 function that just updates the windows directly, but I showed 2 just to make the point.

A couple of side notes:

  1. I'm not a tkinter expert, but I think you want to put your output in tk.labels because they are output and you aren't looking for any data entry, and it's easier. I'm sure you can monkey with the formatting to make it look prettier... not my forte.

  2. In order to have visibility on the window variables, you need to be accessing them from the same scope in which they are defined. In your case, this is inside your main function, so I moved your "helper functions" to be internal functions. There is likely a better structure to be had, and you might review some tk examples for other ideas. This works and makes the point.

Code

import tkinter as tk

def openWagesWindow():
    def CalcWages(gross_pay):
       GP = int(gross_pay) 
       print(GP)
       TX = GP *0.2 
       NI = GP *0.14 
       PNS = GP * 0.08 
       DEDUCT= TX+NI+PNS 
       NET= GP-DEDUCT 
       return (TX,NI,PNS,DEDUCT,NET)   # multiple returns should be tuple, not list

    def update_windows(gross_pay):
        # catch a multiple return with a tuple of variables or just 1 variable 
        # which will be a tuple and split it up later
        (tx, ni, pns, deduct, net) = CalcWages(gross_pay)
        Taxentry['text'] = str(tx)
        NIentry['text'] = str(ni)
        Pensionentry['text'] = str(pns)
        Deductentry['text'] = str(deduct)
        NetPayentry['text'] = str(net)


    WagesWindow=tk.Tk()
    WagesWindow.title("Wages")
    WagesWindow.geometry("800x600")
    windowlabel = tk.Label(WagesWindow, text ="Payroll")
    windowlabel.pack()
                
    Grosslabel = tk.Label(WagesWindow, text= 'Gross Pay')
    Grosslabel.pack()
    Grossentry = tk.Entry(WagesWindow)
    Grossentry.insert(0,int(0))
    Grossentry.pack()

    TaxLabel = tk.Label(WagesWindow, text= 'Tax')
    TaxLabel.pack()
    Taxentry = tk.Label(WagesWindow)
    Taxentry.pack()

    NILabel = tk.Label(WagesWindow, text= 'National Insurance')
    NILabel.pack()
    NIentry = tk.Label(WagesWindow)
    NIentry.pack()

    PensionLabel = tk.Label(WagesWindow, text= 'Pension')
    PensionLabel.pack()
    Pensionentry = tk.Label(WagesWindow)
    Pensionentry.pack()

    Deductlabel = tk.Label(WagesWindow, text= 'Deductions')
    Deductlabel.pack()
    Deductentry = tk.Label(WagesWindow)
    Deductentry.pack()

    NetPaylabel = tk.Label(WagesWindow, text= 'Net Pay')
    NetPaylabel.pack()
    NetPayentry = tk.Label(WagesWindow)
    NetPayentry.pack()

    backbutton = tk.Button(WagesWindow, text= "Back", command= WagesWindow.destroy)
    backbutton.place(x=350, y=350)
        
    calcbutton = tk.Button(WagesWindow, text= "Calculate", 
      command = lambda:update_windows(Grossentry.get()))
    calcbutton.place(x=400, y=350)
    # calcbutton = tk.Button(WagesWindow, text= "Calculate", 
    # command = lambda:CalcWages(Grossentry.get())) 
    
    WagesWindow.mainloop()


openWagesWindow()
AirSquid
  • 10,214
  • 2
  • 7
  • 31