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?
JavaScript
x
71
71
1
from tkinter import *
2
import pandas as pd
3
import matplotlib.pyplot as plt
4
from PIL import ImageTk, Image
5
6
def generate_plot():
7
rate = float(entry_1.get())
8
years_saving = int(entry_2.get())
9
initial_savings = float(entry_3.get())
10
yearly_contribution = float(entry_4.get())
11
12
model = pd.DataFrame({'time': range(years_saving)})
13
model['simple_exp'] = [initial_savings*rate**year for year in model['time']]
14
model['yearly_invest'] = model['simple_exp'] + [yearly_contribution*(rate**year - 1)/(rate-1) for year in model['time']]
15
16
final = model['yearly_invest'].sort_values(ascending= False).iloc[0]
17
18
label_5 = Label(frame, text=f"You would have saved INR {final} by retirement")
19
label_5.grid(row=0, column=0)
20
21
plt.plot(model['time'], model['yearly_invest'])
22
plt.title('Retirement Savings')
23
plt.xlabel('Time in Years)')
24
plt.ylabel('INR (Lacs)')
25
plt.savefig('plot.png')
26
27
load = Image.open('plot.png')
28
render = ImageTk.PhotoImage(load)
29
img = Label(frame, image = render)
30
img.image = render
31
img.grid(row=1, column=0)
32
# my_label = Label(frame, image = my_img)
33
# my_label.grid(row=1, column=0)
34
35
# img = ImageTk.PhotoImage(Image.open('plot.png'))
36
# img_label = Label(frame, image = img)
37
# img_label.grid(row=1, column=0)
38
39
root = Tk()
40
41
label_1 = Label(root, text = 'INTEREST RATE(%)')
42
label_2 = Label(root, text = 'NUMBER OF YEARS IN SAVINGS')
43
label_3 = Label(root, text = 'INITIAL CORPUS (INR LACS)')
44
label_4 = Label(root, text = 'YEARLY CONTRIBUTION (INR LACS')
45
frame = Frame(root, width=300, height=300)
46
button = Button(root, text="GENERATE PLOT", command = generate_plot, padx = 5, pady=5)
47
48
entry_1 = Entry(root)
49
entry_2 = Entry(root)
50
entry_3 = Entry(root)
51
entry_4 = Entry(root)
52
53
label_1.grid(row=0, column=0, pady=5, padx=5)
54
entry_1.grid(row=0, column=1, pady=5, padx=5)
55
56
label_2.grid(row=1, column=0, pady=5, padx=5)
57
entry_2.grid(row=1, column=1, pady=5, padx=5)
58
59
label_3.grid(row=2, column=0, pady=5, padx=5)
60
entry_3.grid(row=2, column=1, pady=5, padx=5)
61
62
label_4.grid(row=3, column=0, pady=5, padx=5)
63
entry_4.grid(row=3, column=1, pady=5, padx=5)
64
65
button.grid(row=4,column=0, columnspan=2, pady=20, padx=5)
66
67
frame.grid(row=5, column=0, columnspan = 2, padx = 5, pady = 5)
68
69
root.mainloop()
70
71
Advertisement
Answer
You can try saving to a stream using BytesIO
:
JavaScript
1
73
73
1
from tkinter import *
2
from io import BytesIO
3
import pandas as pd
4
import matplotlib.pyplot as plt
5
from PIL import ImageTk, Image
6
7
def generate_plot():
8
rate = float(entry_1.get())
9
years_saving = int(entry_2.get())
10
initial_savings = float(entry_3.get())
11
yearly_contribution = float(entry_4.get())
12
13
model = pd.DataFrame({'time': range(years_saving)})
14
model['simple_exp'] = [initial_savings*rate**year for year in model['time']]
15
model['yearly_invest'] = model['simple_exp'] + [yearly_contribution*(rate**year - 1)/(rate-1) for year in model['time']]
16
17
final = model['yearly_invest'].sort_values(ascending= False).iloc[0]
18
19
label_5 = Label(frame, text=f"You would have saved INR {final} by retirement")
20
label_5.grid(row=0, column=0)
21
22
plt.plot(model['time'], model['yearly_invest'])
23
plt.title('Retirement Savings')
24
plt.xlabel('Time in Years)')
25
plt.ylabel('INR (Lacs)')
26
27
img_data = BytesIO()
28
plt.savefig(img_data)
29
30
load = Image.open(img_data)
31
render = ImageTk.PhotoImage(load)
32
img = Label(frame, image = render)
33
img.image = render # This is needed to keep a reference to the image, see the link below
34
img.grid(row=1, column=0)
35
# my_label = Label(frame, image = my_img)
36
# my_label.grid(row=1, column=0)
37
38
# img = ImageTk.PhotoImage(Image.open('plot.png'))
39
# img_label = Label(frame, image = img)
40
# img_label.grid(row=1, column=0)
41
42
root = Tk()
43
44
label_1 = Label(root, text = 'INTEREST RATE(%)')
45
label_2 = Label(root, text = 'NUMBER OF YEARS IN SAVINGS')
46
label_3 = Label(root, text = 'INITIAL CORPUS (INR LACS)')
47
label_4 = Label(root, text = 'YEARLY CONTRIBUTION (INR LACS')
48
frame = Frame(root, width=300, height=300)
49
button = Button(root, text="GENERATE PLOT", command = generate_plot, padx = 5, pady=5)
50
51
entry_1 = Entry(root)
52
entry_2 = Entry(root)
53
entry_3 = Entry(root)
54
entry_4 = Entry(root)
55
56
label_1.grid(row=0, column=0, pady=5, padx=5)
57
entry_1.grid(row=0, column=1, pady=5, padx=5)
58
59
label_2.grid(row=1, column=0, pady=5, padx=5)
60
entry_2.grid(row=1, column=1, pady=5, padx=5)
61
62
label_3.grid(row=2, column=0, pady=5, padx=5)
63
entry_3.grid(row=2, column=1, pady=5, padx=5)
64
65
label_4.grid(row=3, column=0, pady=5, padx=5)
66
entry_4.grid(row=3, column=1, pady=5, padx=5)
67
68
button.grid(row=4,column=0, columnspan=2, pady=20, padx=5)
69
70
frame.grid(row=5, column=0, columnspan = 2, padx = 5, pady = 5)
71
72
root.mainloop()
73
Reference: Why do my Tkinter images not appear?