在 tkinter 环境之外进行绘图时如何嵌入图形对象

How to imbed figure object when plotting occurs outside tkinter environment

有很多网络示例 (1,2,3,4) and threads (,2,3) 关于将绘图嵌入到 tkinter window,但很少有解决在单独环境中绘图并将生成的图形导入 tkinter window.

简而言之,我有一个程序可以计算许多不同的值,并将这些值导出到创建大量绘图的单独文件中。我的 tkinter 应用程序在将它们应用于执行所有计算的主文件之前接受输入框中的参数。通常,我只会按照我链接的示例进行操作,但是由于生成了如此大量的图并且需要能够 select 在给定时间我需要的任何特定图形,这将是低效且耗时的蛮力。一定有更好的方法!

下面是我如何尝试完成此任务的简化示例:


import tkinter as tk
from matplotlib import pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, 
NavigationToolbar2Tk)

import numpy as np


def example_plot(A):
    # Plot generated outside of tkinter environment, but controlled by 
    # variable within tkinter window.
    x = np.linspace(0, 10, 50)
    y = A*x**2
    
    fig, ax = plt.subplots()
    ax.plot(x,y)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    
    return fig


window = tk.Tk()
window.geometry('256x256')
variableEntry = tk.Entry(width = 10)
variableLabel = tk.Label(window, text = "A")


variableEntry.grid(row = 0, column = 0)
variableLabel.grid(row = 0, column = 1)


def plotButton():
    A = variableEntry.get()
    A = int(A)
    
    figure = Figure(figsize = (1,1), dpi = 128)
    add = figure.add_subplot(1,1,1)
    
    example = example_plot(A)
    
    add.imshow(example)
    
    canvas = FigureCanvasTkAgg(figure)
    canvas.get_tk_widget().grid(row = 2, column = 0)
    
    toolbar = NavigationToolbar2Tk(canvas)
    toolbar.update()
    canvas._tkcanvas.grid(row = 3 , column = 0)
    canvas.show()
    

applyButton = tk.Button(master = window, text = "Apply", command = plotButton)
applyButton.grid(row = 1,column = 0)

window.mainloop()

当我 运行 将 A 设置为某个整数并按应用时,出现错误

TypeError: Image data of dtype object cannot be converted to float

看来 add.imshow() 不喜欢我给它喂这个数字。有什么方法可以获取图形(即:example = example_plot(A))并存储它以备后用?

试试这个:

import tkinter as tk
from matplotlib import pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, \
                                              NavigationToolbar2Tk

import numpy as np


def example_plot(A):
    # Plot generated outside of tkinter environment, but controlled by 
    # variable within tkinter window.
    x = np.linspace(0, 10, 50)
    y = A*x*x # This should run slightly faster

    fig, ax = plt.subplots()
    ax.plot(x,y)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    
    return fig


window = tk.Tk()
frame = tk.Frame(window)
frame.pack()
variable_entry = tk.Entry(frame, width=10)
variable_label = tk.Label(frame, text="A")


variable_entry.pack(side="left", fill="x")
variable_label.pack(side="left")


def plot():
    A = int(variable_entry.get())
    
    figure = Figure(figsize=(1, 1), dpi=128)
    add = figure.add_subplot(1, 1, 1)
    
    figure = example_plot(A)
    
    canvas = FigureCanvasTkAgg(figure)
    canvas.get_tk_widget().pack()
    
    toolbar = NavigationToolbar2Tk(canvas, window)
    toolbar.update()
    canvas.get_tk_widget().pack()
    # canvas.show() # There is no need for this
    

apply_button = tk.Button(window, text="Apply", command=plot)
apply_button.pack(fill="x")

window.mainloop()

你的 example_plot returns 一个 Figure 所以你可以使用 figure = example_plot(A) 然后 FigureCanvasTkAgg(figure)。我还添加了一个框架,并试图让一切看起来更好。