I'm fairly new to Python/Pandas/Tkinter and I'm attempting to build a tkinter application that can receive numerical inputs and then perform a WAC (weighted average coupon rate) calculation based on the given input.
I bring in a dataset via pandas dataframe with three columns - Original Amount, Loan Rate and Special Project Code. I then create a new column, Rate Weight, that is the product of the Original Amount and Loan Rate columns.
The purpose of the app is to receive input from a user for a certain code value that changes the row values in the Loan Rate column based on what interest rate input they give, then a new WAC calculation is performed and shown. So far I only have one input box for one code, code 3231 (not shown above in the sample image).
When I run the app and input a numerical value in the box and click 'Calculate WAC' it returns the normal WAC value of the dataset, but not a WAC value performed with the new interest rate for code 3231. It seems to me I'm not capturing the value for the rate and properly and replacing the old with the new.
from tkinter import *
from random import randint
import pandas as pd
root = Tk()
root.title("Financing Grid")
root.geometry("600x600")
global df
df = pd.read_excel("C:\\Users\\mhorv656\\Documents\\Financing Grid v4.xlsx", "Data",
engine = 'openpyxl', usecols = ['ORIG_AMT', 'LOAN_RATE', 'SPECIAL_PROJ_CD'])
df['ORIG_AMT'] = df['ORIG_AMT'].fillna(0).astype(int)
df["Rate_WT"] = df["ORIG_AMT"] * df["LOAN_RATE"]
df['SPECIAL_PROJ_CD'] = df['SPECIAL_PROJ_CD'].fillna(0).astype(int)
# Codes
def c3231_code():
c3231_frame.pack(fill = "both", expand = 1)
# Creating Input Box
global c3231_input
#c3231_input = IntVar()
c3231_input = Entry(c3231_frame)
c3231_input.pack(pady = 5)
# Creating Answer Button
c3231_button = Button(c3231_frame, text = "Calculate WAC", command = c3231_wac)
c3231_button.pack(pady = 5)
# Creating Correct or Incorrect Message
global c3231_label
c3231_label = Label(c3231_frame, text = "Enter Rate Above")
c3231_label.pack(pady = 5)
def c3231_wac():
df.loc[df['SPECIAL_PROJ_CD'] == '3231', 'LOAN_RATE'] = int(c3231_input.get())
WAC = df["Rate_WT"].sum() / df["ORIG_AMT"].sum()
WAC_label = Label(c3231_frame, text = WAC)
WAC_label.pack(pady = 5)
# Clearing the answer box
c3231_input.delete(0, 'end')
# Creating a Hide Frame Function
def hide_menu_frames():
# Destroying the children widgets in each frame
for widget in c3231_frame.winfo_children():
widget.destroy()
# Hiding all frames
c3231_frame_frame.pack_forget()
start_frame.pack_forget()
# Creating Frames
c3231_frame = Frame(root, width = 400, height = 400)
start_frame = Frame(root, width = 400, height = 400)
# Creating Start Screen
def home():
start_frame.pack(fill = "both", expand = 1)
start_label = Label(start_frame, text = "Performing WAC Calculation", font = ("Helvetica", 18)).pack(pady = 40)
# Creating buttons to codes
c3231_button = Button(start_frame, text = "Enter Rate for 3231", command = c3231_code).pack(pady = 5)
# Defining a Main Menu
my_menu = Menu(root)
root.config(menu = my_menu)
# Creating Menu Items
app_menu = Menu(my_menu)
my_menu.add_cascade(label = "Finance Grid", menu = app_menu)
app_menu.add_separator()
app_menu.add_command(label = "Exit", command = root.quit)
# Showing the Start Screen
home()
root.mainloop()
In the c3231_wac() function you are comparing an int value with the string 'SPECIAL_PROJ_CD'] == '3231', change: 3231.
After the replacement, you must recalculate the value of the "Rate_WT" column and only then calculate the WAC.
Related
I am trying to get tkinter to be able to find the total cost of some services that I input into the GUI. I haven't been able to get the actual calculations in the function "myClicker" to return any values to the screen. Looking for some help as to how I can get this code to take the inputs and use them for the calculations. I put in plenty of notes to try and help out too. This is my second post, go easy on me , Thanks!
import tkinter
service = { #This is the dictionary that holds all of the services and their associated prices
'Mergers and Acquisitions':3000,
'Business Valuations':2000,
'Financial Analysis & Operational Ideas':5000,
'Strategic Planning Services':3500,
'Specialized Strategic Consultion Services':4000,
'Litigation Support':6000,
'': 0
}
services = [ #This is the list that holds all of the services (Used for the GUI output)
'',
'Mergers and Acquisitions',
'Business Valuations',
'Financial Analysis & Operational Ideas',
'Strategic Planning Services',
'Specialized Strategic Consultion Services',
'Litigation Support'
]
window = tkinter.Tk() #Creates the window (GUI)
class QuotaCalc:
## A class that asks for data about a client and then calculates
## both the time required for the service and the total estimate cost
def __init__(self, main, cust_name = 'none', co_size = 0, option1=None, option2=None, option3=None): ##This initializes the class with all of the variables that we will use
self.co_name = tkinter.Label(main, text = 'Customer/Company Name', font=('Arial Narrow', 20)).grid(row=20, column=1) #This displays text, the font is the font, and this tells the program what to display
self.co_name_input = tkinter.Entry(main).grid(row=20, column=3) #Allows user to input information #by putting both on row 0, it aligns the text
#can add in blank labels to space out the boxes (reduce the font to something small) on the GUI
clicked = tkinter.StringVar() #initializing "clicked" as a string variable
clicked2 = tkinter.StringVar()
clicked3 = tkinter.StringVar()
clicked.set(services[0]) #Text to be displayed on the menu dropdown
clicked2.set(services[0])
clicked3.set(services[0])
timeRequired = 0 #Initializing the variable timeRequired
comp_size_input = tkinter.IntVar() #Initializing the variable comp_size_input, to be called later in the myClicker function for the calculation
self.co_size = tkinter.Label(main, text = 'Company Size', font=('Arial Narrow', 20)).grid(row=40, column=1) #Company Size Label
self.comp_size_input = tkinter.Entry(main) #Company Size Input Box
self.comp_size_input.grid(row=40, column=3) #Packing the Company Size Label
self.option_1 = tkinter.Label(main, text = 'Service 1 Needed', font=('Arial Narrow', 20)).grid(row=60, column=1) #Service Label
drop = tkinter.StringVar() #Initalizing the variable drop (for the drop box input)
self.drop = tkinter.OptionMenu( main , clicked , *service ) #DropBox Entry Options
self.drop.grid(row = 60, column = 3) #packs the variable drop to the screen at the grid coordinates
#dropped = tkinter.StringVar(drop) Done in the myClicker function
self.option_2 = tkinter.Label(main, text = 'Service 2 Needed', font=('Arial Narrow', 20)).grid(row=80, column=1) #Service 2 Label
drop2 = tkinter.StringVar() #Initalizing the variable drop2 (for the drop box input)
self.drop2 = tkinter.OptionMenu( main , clicked2 , *service ) #DropBox Entry Options
self.drop2.grid(row = 80, column = 3) #packs the variable drop2 to the screen at the grid coordinates
#dropped2 = tkinter.StringVar(drop2)
self.option_3 = tkinter.Label(main, text = 'Service 3 Needed', font=('Arial Narrow', 20)).grid(row=100, column=1) #Service 3 Label
drop3 = tkinter.StringVar() #Initalizing the variable drop3 (for the drop box input)
self.drop3 = tkinter.OptionMenu( main , clicked3 , *service ) #DropBox Entry Options
self.drop3.grid(row = 100, column = 3) #packs the variable drop3 to the screen at the grid coordinates
#dropped3 = tkinter.StringVar(drop3)
self.bt = tkinter.Button(main, text='Calculate', command = self.myClick, fg = "purple", bg = "light blue").grid(row=120, column=2) #Creates the Calculate button to run the code that finds the total cost and time required ##fg is foreground (color), bg is background (color)
#Need to convert to when the button presses, it runs other functions of the class
time_req = tkinter.Label(window, text = 'Time Required', font=('Arial Narrow', 20)).grid(row=140, column=1) #Creates the label Time Required to describe the output
total_cost = tkinter.Label(window, text = 'Price Quote', font=('Arial Narrow', 20)).grid(row=160, column=1) #Creates the label Total Cost to describe the output
#To fix the calcuation problem, maybe make a boolean to see if the button has been clicked and set it to false, when the boolean becomes true run the functions that do the math?
def myClick(self): #A function that activates once the button has been clicked and is desigend to calculate the total cost and time required for the services and output it to the GUI
comp_size = self.comp_size_input.get() #Initalizes the variable copm_size to be used in the time required calcuation
comp_size = int(comp_size) #Converts the variable comp size into an int
drop = str(self.drop) #Initializes and converts the chosen options for services 1, 2, and 3 into a string so they can be used to look up the prices in the service dictionary
drop2 = str(self.drop2)
drop3 = str(self.drop3)
timeRequired = 0
cost = 0
if comp_size == 0: #This determines how much time will be necessary based on the size of the company
self.timeRequired = 0 #Need to add data validation for the company size
elif comp_size <= 20:
self.timeRequired = 1
elif comp_size <= 40:
self.timeRequired = 2
elif comp_size <= 60:
self.timeRequired = 3
elif comp_size <= 80:
self.timeRequired = 4
elif comp_size <= 100:
self.timeRequired = 5
elif comp_size <= 150:
self.timeRequired = 6
else:
self.timeRequired = 8
cost = timeRequired * service[drop] #This section is used to determine the total costs based off of the services and the amount of time for the all the services
if self.drop2 != '':
cost += self.timeRequired * service[drop2]
if self.drop3 != '':
cost += self.timeRequired * service[drop3]
myLabel = tkinter.Label(window,text = timeRequired) #Designed to show the total time required and the total cost outputted on the GUI screen
myLabel.grid(row=140, column=3)
myLabel2 = tkinter.Label(window, text = cost)
myLabel2.grid(row=160, column=3)
logo = tkinter.PhotoImage(file=r"C:\Users\brian\OneDrive\Documents\TCU\Junior Year\Second Semester\Business Information System Development INSC 30833\Bar Ad Pic.PNG")
##YOU MUST USE THE FILE PATH TO THE LOGO ON YOUR OWN COMPUTER
##THIS SHOWS MY PERSONAL FILE PATH
w1 = tkinter.Label(window, image=logo).grid(row=0, column = 2) #Displays the picture at this grid coordinate
window.title('Barrington Advisory Quota Calculator') #Window Title
window.geometry('1000x500') #Sets the size of the window
#window.configure(bg='light blue') <- If we want to change the color of the background
e = QuotaCalc(window)
window.mainloop() #Tells the program to continue running until the GUI is closed
Note: The below code can be used by OP and anybody else with a little bit of tweaking.
Options like the ones in the comments (like Matiiss' comment on using StringVar(), which I am using here) may be more helpful to you, but I'd do it this way (there are many ways to do it, but I chose this one):
import tkinter
from tkinter import ttk # This is to import *most* of the elements you need for a decent-ish GUI w/o calling "tkinter" then elemtent name. I do this because I am lazy
# Setting up the GUI
window = tkinter.Tk()
window.title('Barrington Advisory Quota Calculator') # Window Title
window.geometry('500x500') # Sets the size of the window. Edit this to suit you. I am gonna put 500x500 because I am fine with it
#window.configure(bg='light blue') # If we want to change the color of the background (optional)
window.resizable(False, False) # Make sure that the current user cannot resize the window, keeping it at a fixed size
# Some variables that are kinda important to OP's project (OP, uncomment the line below)
# logo = tkinter.PhotoImage(file=r"C:\Users\brian\OneDrive\Documents\TCU\Junior Year\Second Semester\Business Information System Development INSC 30833\Bar Ad Pic.PNG")
currentSelected = tkinter.StringVar() # Kind of like doing 'currentSelected = ""' but with a bit of a special use later
# Functions
def fetch():
localCurSel = currentSelected.get() # Local variable to keep things easy imo
# BIG DISCLAIMER:
# I have no idea what is going on with the program OP is trying to make for a project
# as I am very new to Python (~4 months)
# Everything after the last line of this function can be expanded to OP's or anyone's
# needs. So if you wanna do some fancy stuff with it, go ahead. What's next is how to display
# the value from this function
leaveMeEmpty.configure(text="Output: {0}".format(localCurSel)) # This is how you display the output of the function
# I don't really get the "self" parameter much, so let's do this on how I'd write this
# GUI Variables
# NOTE: ALWAYS put functions ahead of GUI variables ESPECIALLY when calling a function with a variable
intrLabl = ttk.Label(window, text="Barrington Advisory Quota Calculator")
serviceList = ttk.Combobox(window, textvariable=currentSelected, width=50)
serviceList["values"] = ( # This is the list that holds all of the services for the combobox
'',
'Mergers and Acquisitions',
'Business Valuations',
'Financial Analysis & Operational Ideas',
'Strategic Planning Services',
'Specialized Strategic Consultion Services',
'Litigation Support'
)
serviceCalcul8 = ttk.Button(window, text="Calculate the ", command=fetch)
leaveMeEmpty = ttk.Label(window, text="Output: ") # Variable kinda empty, eh? This is where I-can't-Explain-Further-than-This-because-I-am-a-noob-land begins
# Combobox configs
serviceList["state"] = "readonly" # Make sure that the user cannot change what's inside the combobox except for the ones only in line 19
# Placing the elements/GUI parts thingy
intrLabl.pack()
serviceList.pack(padx=10, pady=10)
serviceCalcul8.pack(padx=10)
leaveMeEmpty.pack(padx=10)
window.mainloop()
I documented it/filled it with comments because it might help someone understand what's going on in a line, for example
When making a program for a game database, I want to have the main menu to have multiple buttons leading to multiple topics. The place function isn't working for me. Here is my code:
windowFU = tk.Tk()
windowFU.title("MHFU Database")
windowFU.geometry("255x200+300+180")
frame = tk.Frame(master = windowFU, width = 255, height = 200)
frame.pack()
icon = tk.PhotoImage(file = "images/icon.png")
windowFU.iconphoto(False, icon)
welcome = tk.Label(
master = frame,
text = "What would you like to view?",
width = 30,
height = 2
)
searchEntry = tk.Entry(
master = frame,
width = 30
)
buttonMonstersFU = tk.Button(
master = frame,
text = "Monsters",
width = 12,
height = 2
)
# Here is the place function
buttonMonstersFU.place(x = 100, y = 100)
welcome.pack()
searchEntry.pack()
buttonMonstersFU.pack()
searchEntry.bind('<Return>', getEntry)
windowFU.mainloop()
Note: Currently I just have the place function set to x = 100, y = 100 to test, it is not my final location.
Here is an image of what I get:
Result
What should I do?
You call buttonMonstersFU.pack() a few lines after you call buttonMonsersFU.place(...). Only one of pack, place, or grid can be responsible for a widget. When you call pack, any work done by place will be thrown away.
If you want to use place, then remove the line that calls buttonMonstersFU.pack().
Here's the code I have written. It's supposed to ask the user for the user's home value and return an assessment value and taxes due.
I'm not sure whether there's an issue with the IDLE on my computer or with my program.
The program is supposed to:
1. ask the user to input their home value
2. give back the assessment value
3. include at least 2 buttons
4. Work (obviously)
import tkinter
class PropertyTaxApp:
def __init__(self):
# Creates main Window
self.main_window
tkinter.mainloop()
#Creates the four frames
self.homevalue_frame = tkinter.Frame(self.main_window)
self.assessmentvalue_frame = tkinter.Frame(self.main_window)
self.propertytaxes_frame = tkinter.Frame(self.main_window)
self.button_frame = tkinter.Frame(self.main_window)
#Create and pack the widgets for the home value
self.homevalue_label = tkinter.Label(self.homevalue_frame,
text = "Enter your home's value here: ")
self.homevalue_entry = tkinter.Entry(self.homevalue_frame,
width=10)
self.homevalue_label.pack(side="left")
self.homevalue_entry.pack(side="left")
#Create and pack the widgets for the assessment value
self.result_label = tkinter.label(self.assessmentvalue_frame,
text="Assessment Value: ")
self.assessmentvalue_label = tkinter.label(self.assessmentvalue_frame,
textvariable=self.assessmentvalue)
self.result_label.pack(side="left")
self.assessmentvalue_label.pack(side="left")
#Create and pack the widgets for the property taxes
self.result_label = tkinter.label(self.propertytaxes_frame,
text="Property Taxes: ")
self.propertytaxes_label = tkinter.label(self.propertytaxes_frame,
textvariable=self.propertytaxes)
self.result_label.pack(side="left")
self.assessmentvalue_label.pack(side="left")
#Create and pack the button widgets
self.calculate_button = tkinter.Button(self.button_frame,
text="Calculate",
command=self.calc_info)
self.quit_button = tkinter.Button(self.button_frame,
text="Quit Program",
command=self.main_window.destroy)
self.calculate_button.pack(side="left")
self.quit_button.pack(side="left")
#Pack frames
self.homevalue_frame.pack()
self.assessmentvalue_frame.pack()
self.propertytaxes_frame.pack()
self.button_frame.pack()
#Start the main loop
tkinter.mainloop()
#the calc_info method is used in the calculate_button widget
def calc_info(self):
#set constants
self.assessmentvaluepct = 0.6
self.propertytaxespct = 0.0075
#get home value input by user
self.homevalue = float(self.homevalue_entry.get())
#calculate the assessment value and property taxes
self.calculatedassessmentvalue=(self.assessmentvaluepct*self.homevalue)
self.calculatedpropertytaxes=(self.propertytaxespct*self.homevalue)
#update the propertytaxes_label widget
self.propertytaxes.set(self.calculatedpropertytaxes)
#update the assessmentvalue_label widget
self.assessment.set(self.calculatedassessmentvalue)
#Run the PropertyTaxApp Class
property_tax_app = PropertyTaxApp()
Thanks so much in advance!
I'm trying to open a second window (defined by the function 'learn') from the main program - the window opens with no problem but the buttons/images don't show up. Does anyone know what I'm doing wrong? All the images are .gif files and sit in the same folder as the program.
I wrote the code under 'learn' in a separate python file. Initially I had tried to open that file as a separate program but it didn't work.
from tkinter import *
import linecache
import os
root = Tk()
root.geometry('1200x800') #Dimensions of the window
root.title("stud(y)ious") #title of the window
container1 = Frame(root)
container1.pack(side = TOP, anchor = W)
container2= Frame(root) #Bottom container
container2.pack(side = BOTTOM,pady = 50) #space between the bottom of the timetable and the two buttons; initially this was cropping the timetable too much so this value was DECREASED in order to shorten the amount of padding that exists around the two buttons at the bottom
#All the images used on the home page; keeping them all in one place so they can be eaisly replaced by anotehr programmer if need be
imgNote = PhotoImage(file='img_note.gif') #'N O T E'
imgHeader = PhotoImage(file='img_title.gif') #'stud(y)ious' 'T I M E T A B L E'
imgTimetable = PhotoImage(file='btn_timetable.gif') #replacable timetable image
imgCreateBtn = PhotoImage(file='btn_create.gif') #'create'
imgLearnBtn = PhotoImage(file='btn_learn.gif') #'learn'
toolbar = Canvas()
Header = Label(toolbar, image = imgHeader).pack() #creation of header, space for imgHeader; above and seperated from main buttons
toolbar.pack()
def destroy(): #closing the window
root.destroy()
def create(): #The window that appears when the 'create' button is clicked
toplevel = Toplevel()
labelCreateHeader = Label(toplevel, image=imgNote) #header graphic
labelCreateHeader.pack()
labelCreateText = Label(toplevel, text=txtCreate) #text (from variable noted below)
labelCreateText.pack()
def learn(): #The window that appears when the 'learn' button is clicked
window1 = Tk()
window1.geometry('1200x800')
window1.title("stud(y)ious: Learn") #title of the window, colon to show connection to studyious_main.py
#Opens the questions file (in read mode) and makes a list of them, one per line
with open('studyious_questions.txt', 'r+') as questionfile:
questions = questionfile.readlines()
#Takes off the '\n' from the end of each line so they are neatly presented and easy to read
questions = [i.strip('\n') for i in questions]
#reading answers; holds a string only - default value ""; type checking
ans1 = StringVar()
ans2 = StringVar()
ans3 = StringVar()
ans4 = StringVar()
ans5 = StringVar()
answers = []
for i in range(1,9):
answers.append(linecache.getline('studyious_answers.txt', i))
answers = [i.strip('\n') for i in answers]
def destroy2():
window1.destroy() #closes window, function attached to '⬅' button
def answering(answer, index): #The window that appears when the 'create' button is clicked
toplevel = Toplevel()
labelCorrectHeader = Label(toplevel, text=txtInfoCorrect, image=imgCorrect) #header graphic
labelCorrect = Label(toplevel, text=txtInfoCorrect) #text (from variable noted below)
labelIncorrectHeader = Label(toplevel, text=txtInfoIncorrect, image=imgIncorrect)
labelIncorrect = Label(toplevel, text=txtInfoIncorrect)
if answer == answers[index]: #selection structure to decide whether the 'correct' (if) or 'incorrect' (else) window pops up
labelCorrectHeader.pack()
labelCorrect.pack()
else:
labelIncorrectHeader.pack()
labelIncorrect.pack()
#The following two text variable were written using triple quotations so the program would register line breaks effectively
txtInfoCorrect = """
Keep up the good work!
Remember, for every 10 questions, take a lil' break <3
"""
txtInfoIncorrect = """
Better luck next time!
Keep going, you can do it!
"""
container01 = Frame(window1)
container01.pack(anchor = W)
ButtonQuit = Button(container01, command=destroy2) #FIXME should open the other python file, containing the homepage
ButtonQuit["text"] = "⬅"
ButtonQuit.pack(side = LEFT, padx = 10, pady = 8)
#Directory of images used in this program
imgCorrect = PhotoImage(file='img_correct.gif')
imgIncorrect = PhotoImage(file='img_incorrect.gif')
imgAnswer = PhotoImage(file='btn_answer.gif')
imgHeaderb = PhotoImage(file='img_header.gif')
toolbar1 = Canvas()
Header1 = Label(toolbar1, image = imgHeaderb).pack() #Placing the header image (img_header) at the top of the page
toolbar1.pack()
#THE QUESTIONS
question1 = Label(window1, text=questions[0]).pack(pady = 10) #states the question according to it's number in the list (e.g this one is 0 because it is the first item in the studyious_questions.txt file
#pady refers to the space between each of teh questions (so things dont look too cluttered and unprofessional)
entry1= Entry(window1, textvariable = ans1) #User can cnter answer to to entry box
entry1.pack()
ButtonAnswer1 = Button(image = imgAnswer,command=lambda:answering(ans1.get(), 0)).pack() #answer button, when clicked entered answer will be checked against teh answer recorded in studyious_answers.txt to see if it is correct
#For example, for the example above, the answer entered by the user is checked against the first answer in the list of answers (index of 0) to see if it correct; promopting a response from the variable 'answering' (which will either produce the 'correct' or 'incorrect dialogue window)
question2 = Label(window1, text=questions[1]).pack(pady = 10)
entry2= Entry(window1, textvariable = ans2)
entry2.pack()
ButtonAnswer2 = Button(image = imgAnswer,command=lambda:answering(ans2.get(), 1)).pack()
question3 = Label(window1, text=questions[2]).pack(pady = 10)
entry3= Entry(window1, textvariable = ans3)
entry3.pack()
ButtonAnswer3 = Button(image = imgAnswer,command=lambda:answering(ans3.get(), 2)).pack()
question4 = Label(window1, text=questions[3]).pack(pady = 10)
entry4= Entry(window1, textvariable = ans4)
entry4.pack()
ButtonAnswer4 = Button(image = imgAnswer,command=lambda:answering(ans4.get(), 3)).pack()
question5 = Label(window1, text=questions[4]).pack(pady = 10)
entry5= Entry(window1, textvariable = ans5)
entry5.pack()
ButtonAnswer5 = Button(image = imgAnswer,command=lambda:answering(ans5.get(), 4)).pack()
window1.mainloop()
txtInfo = """
text
"""
txtCreate = """
text
"""
def timetable():
toplevel = Toplevel() #Ensure window pops up above the main window as a pop up window
labelTimetableHeader = Label(toplevel, image=imgNote) #header graphic to match aesthetic of the rest of the program
labelTimetableHeader.pack()
labelTimetableText = Label(toplevel, text=txtInfo) #The main body of text (as seen above in txtInfo)
labelTimetableText.pack()
btnQuit = Button(container1,command=destroy) #Quit button, closes window
btnQuit["text"] = "Quit"
btnQuit.pack(side = LEFT, padx = 10, pady = 8) #the difference between the top and left padding is that there is automatically two points of padding from the top of the window
TimetableButton = Button(image = imgTimetable,command=timetable).pack() #a replacable image that allows users to enter place their own timetable on the home page
#Initially the button sat squished in the corner whih made the finishing of the home page look very rough, cluttered and unprofessional
#Button 1; opens a small window giving the user details of how to enter the questions and answers they wish to test themselves on
btnCreate = Button(container2, image = imgCreateBtn,command=create).pack(side = LEFT, padx =100) #padding around teh sides seperates the two buttons - 'create' and 'learn'
#Button 2; redirect to the quiz program, opening another window with the quiz program
btnLearn = Button(container2, image = imgLearnBtn,command=learn).pack(side = BOTTOM, padx = 100)
root.mainloop()
You forgot to put window1 as the master of any of your buttons like this one:
ButtonAnswer1 = Button(image = imgAnswer,command=lambda:answering(ans1.get(), 0)).pack()
add window1 to all your ButtonAnswer1-5:
ButtonAnswer1 = Button(window1, image = imgAnswer,command=lambda:answering(ans1.get(), 0)).pack()
I am supposed to write a program with check buttons that allow the user to select any or all of these services. When the user clicks a button the total charges should be displayed. I already have the first portion done and finished but I need help with the second part. I can't find a calculation that works when the user clicks the buttons and the total charges are calculated and displayed within the same box. What is the correct calculation to add the selected? Here's what I have so far:
#Create the checkbutton widgets in top frame.
self.cb1 = tkinter.Checkbutton(self.top_frame, \
text = 'Oil Change-$30.00', variable = self.cb_var1)
self.cb2 = tkinter.Checkbutton(self.top_frame, \
text = 'Lube Job-$20.00', variable = self.cb_var2)
self.cb3 = tkinter.Checkbutton(self.top_frame, \
text = 'Radiator Flush-$40.00', variable = self.cb_var3)
self.cb4 = tkinter.Checkbutton(self.top_frame, \
text = 'Transmission Flush-$100.00', variable = self.cb_var4)
self.cb5 = tkinter.Checkbutton(self.top_frame, \
text = 'Inspection-$35.00', variable = self.cb_var5)
self.cb6 = tkinter.Checkbutton(self.top_frame, \
text = 'Muffler Replacement-$200.00', variable = self.cb_var6)
self.cb7 = tkinter.Checkbutton(self.top_frame, \
text = 'Tire Rotation-$20.00', variable = self.cb_var7)
#Pack the checkbuttons.
self.cb1.pack()
self.cb2.pack()
self.cb3.pack()
self.cb4.pack()
self.cb5.pack()
self.cb6.pack()
self.cb7.pack()
#Create an OK button and Quit button.
self.ok_button = tkinter.Button(self.bottom_frame, \
text = 'OK', command = self.show_choice)
self.quit_button = tkinter.Button(self.bottom_frame, \
text = 'Quit', command = self.main_window.destroy)
#Pack the buttons.
self.ok_button.pack(side = 'left')
self.quit_button.pack(side = 'left')
#Pack frame.
self.top_frame.pack()
self.bottom_frame.pack()
I am not a tkinter person but I would do it as if I was making this in wxpython and you will just have to translate it from there.
So first I would make a dictionary of all checkbox names and the price associated with it. It would look something like this:
priceCheckUp = {"Oil Change-$30.00":30, "Lube Job-$20.00":20...} #Keep going with all the rest of them
Next you would want list of all the checkboxes. I would change your code to have your checkboxes appended to a list like:
checkboxes = []
checkboxes.append(tkinter.Checkbutton(self.top_frame, \
text = 'Oil Change-$30.00', variable = self.cb_var1)) #Do that for all of them
So now that you have a list, you can use a for loop like such after the user presses the button:
total = 0
for i in checkboxes:
if i.isChecked():
total = total + priceCheckUp[i.GetLabel()]
print total #Or display the data however you want
The above code was done for wxPython Checkboxes so you will have to do some translating.
Here's an implementation of the essence of what I said in my comment. Although it's based on the code in your answer, I've added a lot of supporting code so I could test it. One significant change I made was to put all the Checkbutton widgets and their associated control variables into lists instead of explicitly giving each one a unique name — which was getting out-of-hand you have so many of them.
That said, the checking of the state of each Checkbutton and adding up the costs of checked items in shown in the show_choice() method.
import tkinter
# Table of services containing their names and costs.
SERVICES = [('Oil Change', 30.00),
('Lube Job', 20.00),
('Radiator Flush', 40.00),
('Transmission Flush', 100.00),
('Inspection', 35.00),
('Muffler Replacement', 200.00),
('Tire Rotation', 20.00)]
class MyApp(tkinter.Frame):
def __init__(self, master=None):
tkinter.Frame.__init__(self, master)
self.pack()
self.main_window = root
self.top_frame = tkinter.Frame(self)
self.bottom_frame = tkinter.Frame(self)
# Create list of control variables to query state of CheckButtons.
self.cb_vars = [tkinter.IntVar() for _ in range(len(SERVICES))]
# Create another list to hold a corresponding Checkbuttons.
self.cbs = [
tkinter.Checkbutton(
self.top_frame,
text='{}-${:.2f}'.format(SERVICES[i][0], SERVICES[i][1]),
variable=self.cb_vars[i])
for i in range(len(self.cb_vars))
]
# Pack the Checkbuttons.
for i in range(len(self.cbs)):
self.cbs[i].pack()
#Create an OK button and Quit button.
self.ok_button = tkinter.Button(self.bottom_frame,
text='OK', command=self.show_choice)
self.quit_button = tkinter.Button(self.bottom_frame,
text='Quit', command=self.main_window.destroy)
#Pack the buttons.
self.ok_button.pack(side = 'left')
self.quit_button.pack(side = 'left')
#Pack frames.
self.top_frame.pack()
self.bottom_frame.pack()
def show_choice(self):
popup_window = tkinter.Toplevel()
label_frame = tkinter.LabelFrame(popup_window, text='Total Charges')
label_frame.pack()
# Add up the cost of all the items which are checked.
total = sum(SERVICES[i][1] for i in range(len(self.cb_vars))
if self.cb_vars[i].get())
tkinter.Label(label_frame, text='${:.2f}'.format(total)).pack()
# Enter a local mainloop and wait for window to be closed by user.
root.wait_window(popup_window)
root = tkinter.Tk()
app = MyApp(root)
app.master.title('Cost Calculator')
app.mainloop()
Here's a screenshot of it running: