在 Tkinter 标签中嵌入 Matplotlib 图

Embedding Matplotlib plot inside Tkinter Label

我刚刚使用 python 整理了这个基本的退休储蓄计算器。虽然这有效,但我有几个问题:

  1. 有没有办法直接嵌入绘图,即无需将其另存为 PNG 然后再次加载?
  2. 第 30 行显示 img.image = render。虽然我知道这会更新 第 29 行 上定义的标签的图像属性,但我很困惑为什么需要这一行,因为我们已经在第 29 行本身调用了 image = render .为什么两次?
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()

您可以尝试使用 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()

参考:Why do my Tkinter images not appear?