【发布时间】:2017-12-01 22:25:50
【问题描述】:
有人知道如何修改以下代码,以便每次更改测角函数时都更新图表吗?绘图在函数plot() 中完成。 stackoverflow 上有一些相关的线程,但我无法将它们应用到我的示例代码中......
非常感谢,
麦基
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()
【问题讨论】:
-
首先,
tk.Button对self.draw的命令参数应该是self.plot,而不是self.plot() -
两者有什么区别,为什么重要? Python 似乎两者都可以 - 一旦直接绘制图形,在选择函数之后...
-
只创建一次画布,只创建一次绘图并分配给变量
p,_ = a.plot(),然后您可以在不重新创建画布和绘图的情况下替换数据-p.set_ydata(...),p.set_xdata(...) -
command=需要函数名称(回调),例如self.plot- 如果您使用self.plot(),那么它会执行函数self.plot()并分配给从self.plot()返回的command=值跨度> -
@Macky 因为 tkinter 所做的是它试图调用您作为该参数输入的内容(比如我输入
... command = foo它会尝试执行foo()),但如果您执行self.plot(),然后tkinter会尝试调用self.plot()的结果,即None。因此,它会尝试调用None(),这不起作用