Python 在Tkinter中更新画布

Python 在Tkinter中更新画布,python,canvas,tkinter,Python,Canvas,Tkinter,有人知道如何修改下面的代码,以便每次我更改测角函数时图形都会更新吗?打印是在函数plot()中完成的。stackoverflow上有一些相关的线程,但我无法将它们应用到我的示例代码中 许多thx 麦基 您应该在画布上创建空绘图,以后只使用a.set_-xdata(),a.set_-ydata() 将numpy导入为np 将tkinter作为tk导入 从matplotlib.figure导入图形 从matplotlib.backends.backend_tkagg导入图CAVASTKAGG 类应用

有人知道如何修改下面的代码,以便每次我更改测角函数时图形都会更新吗?打印是在函数
plot()
中完成的。stackoverflow上有一些相关的线程,但我无法将它们应用到我的示例代码中

许多thx

麦基


您应该在画布上创建空绘图,以后只使用
a.set_-xdata()
a.set_-ydata()

将numpy导入为np
将tkinter作为tk导入
从matplotlib.figure导入图形
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
类应用程序:
定义初始化(自,窗口):
self.window=window
#设置pi
pi=3.141592654
#创建框架并打包到对象
框架=传统框架(窗口)
frame.pack()
def回调(func,*pargs):
打印(func.get())

#func.set(func.get())#@furas-Thx这篇文章写了很多。根据你在发帖后10分钟的评论得出。虽然我是第二位,但我也将发送我的代码版本;)。我想,我们可以解决这个问题

麦基


首先,
tk.Button
用于
self.draw
的命令参数应该是
self.plot
,而不是
self.plot()
两者之间有什么区别,为什么重要?Python似乎可以同时使用这两种方法-一旦直接绘制图形,在选择函数后的第二次…只创建画布一次,只创建绘图一次并分配给变量
p,
,然后您可以在不使用creaitn的情况下再次替换数据画布和绘图-
p.set\u ydata(…)
p.set\u xdata(…)
command=
需要函数名(回调),如
self.plot
——如果使用
self.plot()
,则它执行函数
self.plot()
,并将从
self.plot()返回的值赋值给
command=
@Macky,因为tkinter所做的是,它尝试调用您作为参数输入的内容(比如我输入
…command=foo
,它会尝试执行
foo()
),但如果执行
self.plot()
,tkinter将尝试调用
self.plot()
的结果,即
。因此,它会尝试调用
None()
,这不起作用。很高兴您仅根据注释得出结论:)现在您可以将您的答案标记为已接受。
import numpy as np
import Tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class App:

    def __init__(self, window):

        self.window = window

        # set up pi
        pi = 3.141592654

        # create the frame and pack to the object
        frame = tk.Frame(window)
        frame.pack()

        def callback(func, *pargs):
            print(func.get())
            func.set(func.get())
            self.plot()
            self.window.update()

        self.func = tk.StringVar()
        self.func.set("sin") # default value
        self.func.trace('w', lambda *pargs: callback(self.func, *pargs))

        self.button = tk.OptionMenu(window, self.func, "sin", "cos", "tan")
        self.button.pack(side = tk.TOP)

        self.min_value = tk.Entry(window, justify = tk.RIGHT)
        self.min_value.pack()

        self.min_value.delete(0, tk.END)
        self.min_value.insert(0, -pi)

        self.max_value = tk.Entry(window, justify = tk.RIGHT)
        self.max_value.pack()

        self.max_value.delete(0, tk.END)
        self.max_value.insert(0, pi)

        self.button = tk.Button(frame, text = "QUIT", foreground = "red", command = frame.quit)
        self.button.pack(side = tk.BOTTOM)

        self.draw = tk.Button(frame, text = "DRAW", command = self.plot())
        self.draw.pack(side = tk.LEFT)

    def plot(self):

        # generate numbers for the plot
        x = np.array(np.arange(np.float64(self.min_value.get()), np.float64(self.max_value.get()), 0.001))

        if self.func.get() == 'sin':
            print('plotting sin()')
            y = np.sin(x)
        elif self.func.get() == 'cos':
            print('plotting cos()')
            y = np.cos(x)
        else:
            print('plotting tan()')
            y = np.tan(x)

        # create the plot
        fig = Figure(figsize = (6, 6))
        a = fig.add_subplot(1,1,1)
        a.plot(x, y, color = 'blue')
        a.set_title ("Goniometric Functions", fontsize = 12)
        a.set_ylabel(self.func.get() + '(x)', fontsize = 8)
        a.set_xlabel('x', fontsize = 8)

        # canvas
        canvas = FigureCanvasTkAgg(fig, master = self.window)
        self.widget = canvas.get_tk_widget().pack()
        print('here I should update canvas')
        canvas.draw()

root = tk.Tk()
app = App(root)   
root.mainloop()
root.destroy()
import numpy as np
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class App:

    def __init__(self, window):

        self.window = window

        # set up pi
        pi = 3.141592654

        # create the frame and pack to the object
        frame = tk.Frame(window)
        frame.pack()

        def callback(func, *pargs):
            print(func.get())
            #func.set(func.get()) # <-- it has no sense
            self.update_plot()
            self.window.update()

        self.func = tk.StringVar()
        self.func.set("sin") # default value
        self.func.trace('w', lambda *pargs: callback(self.func, *pargs))

        self.button = tk.OptionMenu(window, self.func, "sin", "cos", "tan")
        self.button.pack(side = tk.TOP)

        self.min_value = tk.Entry(window, justify = tk.RIGHT)
        self.min_value.pack()

        self.min_value.delete(0, tk.END)
        self.min_value.insert(0, -pi)

        self.max_value = tk.Entry(window, justify=tk.RIGHT)
        self.max_value.pack()

        self.max_value.delete(0, tk.END)
        self.max_value.insert(0, pi)

        self.button = tk.Button(frame, text="QUIT", foreground="red", command=root.destroy) #<--
        self.button.pack(side = tk.BOTTOM)

        self.draw = tk.Button(frame, text="DRAW", command=self.update_plot)
        self.draw.pack(side = tk.LEFT)

        # create empty plot
        self.create_plot()
        # update plot with current function at start
        self.update_plot()

    def create_plot(self):

        # create the plot
        self.fig = Figure(figsize = (6, 6))
        self.a = self.fig.add_subplot(1,1,1)

        self.p, _ = self.a.plot([], [], color = 'blue')

        self.a.set_title ("Goniometric Functions", fontsize = 12)

        # canvas
        self.canvas = FigureCanvasTkAgg(self.fig, master = self.window)
        self.widget = self.canvas.get_tk_widget().pack()
        #self.canvas.draw()

    def update_plot(self):
        print('update')

        # generate numbers for the plot
        x = np.array(np.arange(np.float64(self.min_value.get()), np.float64(self.max_value.get()), 0.001))

        if self.func.get() == 'sin':
            print('plotting sin()')
            y = np.sin(x)
        elif self.func.get() == 'cos':
            print('plotting cos()')
            y = np.cos(x)
        else:
            print('plotting tan()')
            y = np.tan(x)

        # replace labels
        self.a.set_ylabel(self.func.get() + '(x)', fontsize = 8)
        self.a.set_xlabel('x', fontsize = 8)

        # replace data
        self.p.set_xdata(x)
        self.p.set_ydata(y)

        # rescale
        self.a.relim()
        self.a.autoscale_view()

        # update screen
        self.canvas.draw()

root = tk.Tk()
app = App(root)   
root.mainloop()
#root.destroy() You don't need it
import numpy as np
import Tkinter as tk
import matplotlib.figure as fg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class App:

    def __init__(self, window):

        self.window = window

        # set up pi
        pi = 3.141592654

        # create empty canvas
        x = []
        y = []
        fig = fg.Figure(figsize = (4,4))
        fig_subplot = fig.add_subplot(111)
        self.line, = fig_subplot.plot(x, y)
        self.canvas = FigureCanvasTkAgg(fig, master = self.window)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side = tk.TOP, fill = tk.BOTH, expand = 1)

        # create the frame and pack to the object
        frame = tk.Frame(window)
        frame.pack()

        def callback(func, *pargs):
            print(func.get())
            func.set(func.get())
            self.plot()

        self.func = tk.StringVar()
        self.func.set("sin") # default value
        self.func.trace('w', lambda *pargs: callback(self.func, *pargs))

        self.button = tk.OptionMenu(window, self.func, "sin", "cos", "tan")
        self.button.pack(side = tk.TOP)

        self.min_value = tk.Entry(window, justify = tk.RIGHT)
        self.min_value.pack()

        self.min_value.delete(0, tk.END)
        self.min_value.insert(0, -pi)

        self.max_value = tk.Entry(window, justify = tk.RIGHT)
        self.max_value.pack()

        self.max_value.delete(0, tk.END)
        self.max_value.insert(0, pi)

        self.button = tk.Button(frame, text = "QUIT", foreground = "red", command = frame.quit)
        self.button.pack(side = tk.BOTTOM)

    def plot(self):

        # generate numbers for the plot
        x = np.array(np.arange(np.float64(self.min_value.get()), np.float64(self.max_value.get()), 0.001))

        if self.func.get() == 'sin':
            print('plotting sin()')
            y = np.sin(x)
        elif self.func.get() == 'cos':
            print('plotting cos()')
            y = np.cos(x)
        else:
            print('plotting tan()')
            y = np.tan(x)

        # update canvas
        self.line.set_data(x, y)
        ax = self.canvas.figure.axes[0]
        ax.set_xlim(x.min(), x.max())
        ax.set_ylim(y.min(), y.max())        
        self.canvas.draw()

root = tk.Tk()
app = App(root)   
root.mainloop()
root.destroy()