如何根据条目的值立即更新 matplotlib 的颜色条范围?
how to instantly update the colorbar range of a matplotlib from values of entries?
我有一个简单的代码来绘制图形。我想手动更改颜色条的范围。
所以,我添加了两个 Entries
并定义了第二个函数 change()
。我想在没有第二个按钮的情况下立即更改颜色条。
from tkinter import *
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
root = Tk()
root.geometry("500x500")
Max, Min = IntVar(), IntVar()
label1 = Label(root, text="Max")
label1.place(x=10, y=35)
label2 = Label(root, text="Min")
label2.place(x=10, y=60)
entry1 = Entry(root, textvariable=Max, width=5)
entry1.place(x=50, y=35)
entry2 = Entry(root, textvariable=Min, width=5)
entry2.place(x=50, y=60)
def plot():
global x, y
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
def change():
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn', vmin=entry1.get(), vmax=entry2.get())
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)
button2 = Button(root, text="change", command=change)
button2.place(x=80, y=0)
root.mainloop()
我找到了这个post Constantly Update Label Widgets From Entry Widgets TKinter,我尝试使用方法2,我更改了这部分的代码:
...
def auto():
c.config(vmin=entry1.get(), vmax=entry2.get())
entry1 = Entry(root, textvariable=Max, width=5)
entry1.place(x=50, y=35)
entry2 = Entry(root, textvariable=Min, width=5)
entry2.place(x=50, y=60)
auto()
...
但由于 c
是一个局部变量,所以代码不起作用。谁能帮我立即更新颜色条范围?
所以你最终想要的是在用户更改 Min 和 Max 输入时更改颜色图 vmin
和 vmax
。您不需要不断更新颜色图,只需更改这些输入即可。
您可以通过使用更新回调跟踪输入更改来做到这一点。
这是修改后的代码,当最小和最大输入更改时更新颜色图:
from tkinter import *
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
root = Tk()
root.geometry("500x500")
Max, Min = IntVar(), IntVar()
label1 = Label(root, text="Min")
label1.place(x=10, y=35)
label2 = Label(root, text="Max")
label2.place(x=10, y=60)
vmin_entry = Entry(root, textvariable=Min, width=5)
vmin_entry.place(x=50, y=35)
vmax_entry = Entry(root, textvariable=Max, width=5)
vmax_entry.place(x=50, y=60)
# Define global variables
c, canvas = None, None
def plot():
global x, y, c, canvas
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x * y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
canvas.draw()
def update_colormap(*args, **kwargs):
global c, canvas
if c is not None:
try:
# Get vmin and vmax
vmin, vmax = int(vmin_entry.get()), int(vmax_entry.get())
except ValueError:
# Could not convert values to int, non integer value
return
if vmin > vmax:
return
# Set new limits
c.set_clim(vmin, vmax)
# Update plot
canvas.flush_events()
canvas.draw()
# Trace change of Min and Max and call update_colormap as a callabck
Min.trace("w", update_colormap)
Max.trace("w", update_colormap)
button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)
root.mainloop()
您可以将输入小部件的 "<Key>"
事件绑定到更改函数作为回调,这将在输入小部件中输入任何内容时调用更改函数。
entry1.bind('<Key>', lambda x : change())
对两个条目执行此操作会将这些行添加到您的代码中 -:
entry1.bind('<Key>', lambda x : change())
entry2.bind('<Key>', lambda x : change())
完整代码将变为-:
from tkinter import *
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
root = Tk()
root.geometry("500x500")
Max, Min = IntVar(), IntVar()
label1 = Label(root, text="Max")
label1.place(x=10, y=35)
label2 = Label(root, text="Min")
label2.place(x=10, y=60)
entry1 = Entry(root, textvariable=Max, width=5)
entry1.place(x=50, y=35)
entry2 = Entry(root, textvariable=Min, width=5)
entry2.place(x=50, y=60)
def plot():
global x, y
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
def change():
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn', vmin=entry1.get(), vmax=entry2.get())
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)
entry1.bind('<Key>', lambda x : change()) # binding the first entry's keypress event to the change function.
entry2.bind('<Key>', lambda x : change()) # binding the second entry's keypress event to the change function.
root.mainloop()
注意:
只要在小部件内按下某个键,就会触发 "<Key>"
事件的回调,有关详细信息,请查看 events and bindings。
我有一个简单的代码来绘制图形。我想手动更改颜色条的范围。
所以,我添加了两个 Entries
并定义了第二个函数 change()
。我想在没有第二个按钮的情况下立即更改颜色条。
from tkinter import *
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
root = Tk()
root.geometry("500x500")
Max, Min = IntVar(), IntVar()
label1 = Label(root, text="Max")
label1.place(x=10, y=35)
label2 = Label(root, text="Min")
label2.place(x=10, y=60)
entry1 = Entry(root, textvariable=Max, width=5)
entry1.place(x=50, y=35)
entry2 = Entry(root, textvariable=Min, width=5)
entry2.place(x=50, y=60)
def plot():
global x, y
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
def change():
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn', vmin=entry1.get(), vmax=entry2.get())
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)
button2 = Button(root, text="change", command=change)
button2.place(x=80, y=0)
root.mainloop()
我找到了这个post Constantly Update Label Widgets From Entry Widgets TKinter,我尝试使用方法2,我更改了这部分的代码:
...
def auto():
c.config(vmin=entry1.get(), vmax=entry2.get())
entry1 = Entry(root, textvariable=Max, width=5)
entry1.place(x=50, y=35)
entry2 = Entry(root, textvariable=Min, width=5)
entry2.place(x=50, y=60)
auto()
...
但由于 c
是一个局部变量,所以代码不起作用。谁能帮我立即更新颜色条范围?
所以你最终想要的是在用户更改 Min 和 Max 输入时更改颜色图 vmin
和 vmax
。您不需要不断更新颜色图,只需更改这些输入即可。
您可以通过使用更新回调跟踪输入更改来做到这一点。
这是修改后的代码,当最小和最大输入更改时更新颜色图:
from tkinter import *
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
root = Tk()
root.geometry("500x500")
Max, Min = IntVar(), IntVar()
label1 = Label(root, text="Min")
label1.place(x=10, y=35)
label2 = Label(root, text="Max")
label2.place(x=10, y=60)
vmin_entry = Entry(root, textvariable=Min, width=5)
vmin_entry.place(x=50, y=35)
vmax_entry = Entry(root, textvariable=Max, width=5)
vmax_entry.place(x=50, y=60)
# Define global variables
c, canvas = None, None
def plot():
global x, y, c, canvas
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x * y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
canvas.draw()
def update_colormap(*args, **kwargs):
global c, canvas
if c is not None:
try:
# Get vmin and vmax
vmin, vmax = int(vmin_entry.get()), int(vmax_entry.get())
except ValueError:
# Could not convert values to int, non integer value
return
if vmin > vmax:
return
# Set new limits
c.set_clim(vmin, vmax)
# Update plot
canvas.flush_events()
canvas.draw()
# Trace change of Min and Max and call update_colormap as a callabck
Min.trace("w", update_colormap)
Max.trace("w", update_colormap)
button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)
root.mainloop()
您可以将输入小部件的 "<Key>"
事件绑定到更改函数作为回调,这将在输入小部件中输入任何内容时调用更改函数。
entry1.bind('<Key>', lambda x : change())
对两个条目执行此操作会将这些行添加到您的代码中 -:
entry1.bind('<Key>', lambda x : change())
entry2.bind('<Key>', lambda x : change())
完整代码将变为-:
from tkinter import *
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
root = Tk()
root.geometry("500x500")
Max, Min = IntVar(), IntVar()
label1 = Label(root, text="Max")
label1.place(x=10, y=35)
label2 = Label(root, text="Min")
label2.place(x=10, y=60)
entry1 = Entry(root, textvariable=Max, width=5)
entry1.place(x=50, y=35)
entry2 = Entry(root, textvariable=Min, width=5)
entry2.place(x=50, y=60)
def plot():
global x, y
x, y = np.mgrid[slice(0, 100), slice(0, 100)]
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn')
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
def change():
z = (x*y)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
c = ax.pcolormesh(x, y, z, cmap='YlGn', vmin=entry1.get(), vmax=entry2.get())
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=0, y=80)
button1 = Button(root, text="Plot", command=plot)
button1.place(x=30, y=0)
entry1.bind('<Key>', lambda x : change()) # binding the first entry's keypress event to the change function.
entry2.bind('<Key>', lambda x : change()) # binding the second entry's keypress event to the change function.
root.mainloop()
注意:
只要在小部件内按下某个键,就会触发 "<Key>"
事件的回调,有关详细信息,请查看 events and bindings。