I just put together this basic retirement savings calculator using python. While this works, I had a couple of questions:
- Is there a way to embed the plot directly, i.e. without saving it as a PNG and then loading it again?
- Line 30 reads
img.image = render
. While I understand that this updates the image attribute for the label defined on line 29, I am confused why this line is required, since we already call outimage = render
on line 29 itself. Why twice?
from tkinter import * import pandas as pd import matplotlib.pyplot as plt from PIL import ImageTk, Image def generate_plot(): rate = float(entry_1.get()) years_saving = int(entry_2.get()) initial_savings = float(entry_3.get()) yearly_contribution = float(entry_4.get()) model = pd.DataFrame({'time': range(years_saving)}) model['simple_exp'] = [initial_savings*rate**year for year in model['time']] model['yearly_invest'] = model['simple_exp'] + [yearly_contribution*(rate**year - 1)/(rate-1) for year in model['time']] final = model['yearly_invest'].sort_values(ascending= False).iloc[0] label_5 = Label(frame, text=f"You would have saved INR {final} by retirement") label_5.grid(row=0, column=0) plt.plot(model['time'], model['yearly_invest']) plt.title('Retirement Savings') plt.xlabel('Time in Years)') plt.ylabel('INR (Lacs)') plt.savefig('plot.png') load = Image.open('plot.png') render = ImageTk.PhotoImage(load) img = Label(frame, image = render) img.image = render img.grid(row=1, column=0) # my_label = Label(frame, image = my_img) # my_label.grid(row=1, column=0) # img = ImageTk.PhotoImage(Image.open('plot.png')) # img_label = Label(frame, image = img) # img_label.grid(row=1, column=0) root = Tk() label_1 = Label(root, text = 'INTEREST RATE(%)') label_2 = Label(root, text = 'NUMBER OF YEARS IN SAVINGS') label_3 = Label(root, text = 'INITIAL CORPUS (INR LACS)') label_4 = Label(root, text = 'YEARLY CONTRIBUTION (INR LACS') frame = Frame(root, width=300, height=300) button = Button(root, text="GENERATE PLOT", command = generate_plot, padx = 5, pady=5) entry_1 = Entry(root) entry_2 = Entry(root) entry_3 = Entry(root) entry_4 = Entry(root) label_1.grid(row=0, column=0, pady=5, padx=5) entry_1.grid(row=0, column=1, pady=5, padx=5) label_2.grid(row=1, column=0, pady=5, padx=5) entry_2.grid(row=1, column=1, pady=5, padx=5) label_3.grid(row=2, column=0, pady=5, padx=5) entry_3.grid(row=2, column=1, pady=5, padx=5) label_4.grid(row=3, column=0, pady=5, padx=5) entry_4.grid(row=3, column=1, pady=5, padx=5) button.grid(row=4,column=0, columnspan=2, pady=20, padx=5) frame.grid(row=5, column=0, columnspan = 2, padx = 5, pady = 5) root.mainloop()
Advertisement
Answer
You can try saving to a stream using BytesIO
:
from tkinter import * from io import BytesIO import pandas as pd import matplotlib.pyplot as plt from PIL import ImageTk, Image def generate_plot(): rate = float(entry_1.get()) years_saving = int(entry_2.get()) initial_savings = float(entry_3.get()) yearly_contribution = float(entry_4.get()) model = pd.DataFrame({'time': range(years_saving)}) model['simple_exp'] = [initial_savings*rate**year for year in model['time']] model['yearly_invest'] = model['simple_exp'] + [yearly_contribution*(rate**year - 1)/(rate-1) for year in model['time']] final = model['yearly_invest'].sort_values(ascending= False).iloc[0] label_5 = Label(frame, text=f"You would have saved INR {final} by retirement") label_5.grid(row=0, column=0) plt.plot(model['time'], model['yearly_invest']) plt.title('Retirement Savings') plt.xlabel('Time in Years)') plt.ylabel('INR (Lacs)') img_data = BytesIO() plt.savefig(img_data) load = Image.open(img_data) render = ImageTk.PhotoImage(load) img = Label(frame, image = render) img.image = render # This is needed to keep a reference to the image, see the link below img.grid(row=1, column=0) # my_label = Label(frame, image = my_img) # my_label.grid(row=1, column=0) # img = ImageTk.PhotoImage(Image.open('plot.png')) # img_label = Label(frame, image = img) # img_label.grid(row=1, column=0) root = Tk() label_1 = Label(root, text = 'INTEREST RATE(%)') label_2 = Label(root, text = 'NUMBER OF YEARS IN SAVINGS') label_3 = Label(root, text = 'INITIAL CORPUS (INR LACS)') label_4 = Label(root, text = 'YEARLY CONTRIBUTION (INR LACS') frame = Frame(root, width=300, height=300) button = Button(root, text="GENERATE PLOT", command = generate_plot, padx = 5, pady=5) entry_1 = Entry(root) entry_2 = Entry(root) entry_3 = Entry(root) entry_4 = Entry(root) label_1.grid(row=0, column=0, pady=5, padx=5) entry_1.grid(row=0, column=1, pady=5, padx=5) label_2.grid(row=1, column=0, pady=5, padx=5) entry_2.grid(row=1, column=1, pady=5, padx=5) label_3.grid(row=2, column=0, pady=5, padx=5) entry_3.grid(row=2, column=1, pady=5, padx=5) label_4.grid(row=3, column=0, pady=5, padx=5) entry_4.grid(row=3, column=1, pady=5, padx=5) button.grid(row=4,column=0, columnspan=2, pady=20, padx=5) frame.grid(row=5, column=0, columnspan = 2, padx = 5, pady = 5) root.mainloop()
Reference: Why do my Tkinter images not appear?