如何在 tkinter 中使用 matplotlib 中的 rangesliders 功能?
How to use rangesliders feature from matplotlib in tkinter?
我已经编写了一个代码来使用 RangeSldider
小部件来控制我的轴范围。
from tkinter import *
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import cm
from matplotlib.colors import ListedColormap
from RangeSlider.RangeSlider import RangeSliderH, RangeSliderV
root = Tk()
root.geometry("600x600")
def plot():
x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
z = np.arange(1,26).reshape(5,5)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
ax.set_title('mY Title', fontweight="bold")
ax.set_xlabel("X", fontsize=14)
ax.set_ylabel("Y", fontsize=14)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=100, y=25)
figure.patch.set_facecolor('#f0f0f0')
ax.set_xlim(rs1.getValues())
ax.set_ylim(rs2.getValues())
hVar1 = IntVar() # left handle variable
hVar2 = IntVar() # right handle variable
rs1 = RangeSliderH(root, [hVar1, hVar2], Width=230, Height=55, padX=17, min_val=0, max_val=5, font_size=12,\
show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',\
line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')
rs1.place(x=150, y=420)
vVar1 = IntVar() # top handle variable
vVar2 = IntVar() # down handle variable
rs2 = RangeSliderV(root, [vVar1, vVar2], Width=81, Height=180, padY=11, min_val=0, max_val=5, font_size=12,\
show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',\
line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')
rs2.place(x=0, y=150)
button = Button(root, text="Plot", command=plot)
button.pack()
root.mainloop()
我得到了使用 matplotlib
提供的范围滑块功能的建议。我在图书馆中搜索,并使用了 FloatRangeSlider
。但我不知道如何添加范围滑块以在 canvas 上显示并使其工作并立即更新数字 。
from tkinter import *
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap
import ipywidgets as widgets
root = Tk()
root.geometry("600x600")
def plot():
x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
z = np.arange(1,26).reshape(5,5)
figure = Figure(figsize=(8, 8))
ax = figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
ax.set_title('mY Title', fontweight="bold")
ax.set_xlabel("X", fontsize=14)
ax.set_ylabel("Y", fontsize=14)
sliderH = widgets.FloatRangeSlider(value=(0, 5), min=0, max=5, step=1, orientation='horizontal')
sliderV = widgets.FloatRangeSlider(value=(0, 5), min=0, max=5, step=1, orientation='vertical')
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().pack()
def update():
x, y = np.mgrid[slice(sliderH.value[0], sliderH.value[1], 1), slice(sliderV.value[0], sliderV.value[1], 1)]
figure.canvas.draw()
sliderH.observe(update, names='value')
sliderV.observe(update, names='value')
display(sliderH)
display(sliderV)
button = Button(root, text="Plot", command=plot)
button.pack()
root.mainloop()
除非我误解了什么,否则您使用的不是 matplotlib
的 RangeSLider,而是 ipywidgets
。该库用于 Jupyter notebook。
这里是使用 matplotlib 的 RangeSLider 和实时轴范围更新的实现:
from tkinter import *
import matplotlib
import numpy as np
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import cm
from matplotlib.colors import ListedColormap
import matplotlib.widgets as widgets
root = Tk()
root.geometry("600x600")
x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
z = np.arange(1, 26).reshape(5, 5)
figure = Figure(figsize=(8, 8))
# Make figure a bit wider and taller
figure.subplots_adjust(bottom=0.2)
figure.subplots_adjust(left=0.2)
ax = figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
ax.set_title('mY Title', fontweight="bold")
ax.set_xlabel("X", fontsize=14)
ax.set_ylabel("Y", fontsize=14)
# Create X slider
slider_ax = figure.add_axes([0.2, 0.05, 0.6, 0.03])
sliderH = widgets.RangeSlider(slider_ax, "Val", valmin=0, valmax=5, valstep=1, valinit=(0, 5))
# Create Y slider
slider_ay = figure.add_axes([0.05, 0.25, 0.03, 0.6])
sliderV = widgets.RangeSlider(slider_ay, "Val", valmin=0, valmax=5, valstep=1, valinit=(0, 5), orientation='vertical')
def set_x_range(value):
ax.set_xlim(xmin=value[0], xmax=value[1])
def set_y_range(value):
ax.set_ylim(ymin=value[0], ymax=value[1])
sliderH.on_changed(set_x_range)
sliderV.on_changed(set_y_range)
canvas = FigureCanvasTkAgg(figure, root)
canvas.draw()
button = Button(root, text="Plot", command=canvas.get_tk_widget().pack)
button.pack()
root.mainloop()
这是它的样子:
我在垂直滑块方面遇到了一个小问题,按钮仍然处于水平状态。可能只是我的环境问题,也可能是 matplotlib 错误。
您可以通过水平方向使用两个滑块来解决它。
我已经编写了一个代码来使用 RangeSldider
小部件来控制我的轴范围。
from tkinter import *
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import cm
from matplotlib.colors import ListedColormap
from RangeSlider.RangeSlider import RangeSliderH, RangeSliderV
root = Tk()
root.geometry("600x600")
def plot():
x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
z = np.arange(1,26).reshape(5,5)
figure = Figure(figsize=(4, 4))
ax = figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
ax.set_title('mY Title', fontweight="bold")
ax.set_xlabel("X", fontsize=14)
ax.set_ylabel("Y", fontsize=14)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=100, y=25)
figure.patch.set_facecolor('#f0f0f0')
ax.set_xlim(rs1.getValues())
ax.set_ylim(rs2.getValues())
hVar1 = IntVar() # left handle variable
hVar2 = IntVar() # right handle variable
rs1 = RangeSliderH(root, [hVar1, hVar2], Width=230, Height=55, padX=17, min_val=0, max_val=5, font_size=12,\
show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',\
line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')
rs1.place(x=150, y=420)
vVar1 = IntVar() # top handle variable
vVar2 = IntVar() # down handle variable
rs2 = RangeSliderV(root, [vVar1, vVar2], Width=81, Height=180, padY=11, min_val=0, max_val=5, font_size=12,\
show_value=True, digit_precision='.0f', bgColor='#f0f0f0', line_s_color='black',\
line_color='black', bar_color_inner='black', bar_color_outer='#f0f0f0')
rs2.place(x=0, y=150)
button = Button(root, text="Plot", command=plot)
button.pack()
root.mainloop()
我得到了使用 matplotlib
提供的范围滑块功能的建议。我在图书馆中搜索,并使用了 FloatRangeSlider
。但我不知道如何添加范围滑块以在 canvas 上显示并使其工作并立即更新数字 。
from tkinter import *
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap
import ipywidgets as widgets
root = Tk()
root.geometry("600x600")
def plot():
x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
z = np.arange(1,26).reshape(5,5)
figure = Figure(figsize=(8, 8))
ax = figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
ax.set_title('mY Title', fontweight="bold")
ax.set_xlabel("X", fontsize=14)
ax.set_ylabel("Y", fontsize=14)
sliderH = widgets.FloatRangeSlider(value=(0, 5), min=0, max=5, step=1, orientation='horizontal')
sliderV = widgets.FloatRangeSlider(value=(0, 5), min=0, max=5, step=1, orientation='vertical')
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().pack()
def update():
x, y = np.mgrid[slice(sliderH.value[0], sliderH.value[1], 1), slice(sliderV.value[0], sliderV.value[1], 1)]
figure.canvas.draw()
sliderH.observe(update, names='value')
sliderV.observe(update, names='value')
display(sliderH)
display(sliderV)
button = Button(root, text="Plot", command=plot)
button.pack()
root.mainloop()
除非我误解了什么,否则您使用的不是 matplotlib
的 RangeSLider,而是 ipywidgets
。该库用于 Jupyter notebook。
这里是使用 matplotlib 的 RangeSLider 和实时轴范围更新的实现:
from tkinter import *
import matplotlib
import numpy as np
matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import cm
from matplotlib.colors import ListedColormap
import matplotlib.widgets as widgets
root = Tk()
root.geometry("600x600")
x, y = np.mgrid[slice(0, 6, 1), slice(0, 6, 1)]
z = np.arange(1, 26).reshape(5, 5)
figure = Figure(figsize=(8, 8))
# Make figure a bit wider and taller
figure.subplots_adjust(bottom=0.2)
figure.subplots_adjust(left=0.2)
ax = figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, z, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
ax.set_title('mY Title', fontweight="bold")
ax.set_xlabel("X", fontsize=14)
ax.set_ylabel("Y", fontsize=14)
# Create X slider
slider_ax = figure.add_axes([0.2, 0.05, 0.6, 0.03])
sliderH = widgets.RangeSlider(slider_ax, "Val", valmin=0, valmax=5, valstep=1, valinit=(0, 5))
# Create Y slider
slider_ay = figure.add_axes([0.05, 0.25, 0.03, 0.6])
sliderV = widgets.RangeSlider(slider_ay, "Val", valmin=0, valmax=5, valstep=1, valinit=(0, 5), orientation='vertical')
def set_x_range(value):
ax.set_xlim(xmin=value[0], xmax=value[1])
def set_y_range(value):
ax.set_ylim(ymin=value[0], ymax=value[1])
sliderH.on_changed(set_x_range)
sliderV.on_changed(set_y_range)
canvas = FigureCanvasTkAgg(figure, root)
canvas.draw()
button = Button(root, text="Plot", command=canvas.get_tk_widget().pack)
button.pack()
root.mainloop()
这是它的样子:
我在垂直滑块方面遇到了一个小问题,按钮仍然处于水平状态。可能只是我的环境问题,也可能是 matplotlib 错误。
您可以通过水平方向使用两个滑块来解决它。