gpt4 book ai didi

python - 如何在两个图形之间切换并保持单选按钮和 slider 更新工作?

转载 作者:行者123 更新时间:2023-12-04 13:25:04 25 4
gpt4 key购买 nike

我使用 Tkinter 和 matplotlib 在 Python 中制作了一个图形查看器 GUI 程序,我在两个图形之间切换。
我有三个问题我不知道如何解决:

  • 移动滑块后无法更改单选按钮,它停止更新。
  • 切换图表后无法更改单选按钮。
  • 我想在带有 1 个子图和 2 个子图的图形之间切换,但是当我切换到带有滑块和单选条的带有 2 个子图的图形时,我无法回到第一个。

  • 我认为问题可能在于我更新滑块和单选按钮的方式
    这是代码:
    import matplotlib
    import tkinter as Tk
    matplotlib.use("TkAgg")
    import matplotlib.pyplot as plt
    import numpy as np
    from tkinter import *
    from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
    from matplotlib.backend_bases import key_press_handler
    from matplotlib.widgets import Slider, RadioButtons

    # Seperated out config of plot to just do it once
    def config_plot():
    fig, ax = plt.subplots()
    ax.set(xlabel='time (s)', ylabel='voltage (mV)',
    title='Graph One')
    return (fig, ax)


    class matplotlibSwitchGraphs:
    def __init__(self, master):
    self.master = master
    self.frame = Frame(self.master)
    self.fig, self.ax = config_plot()
    self.graphIndex = 0
    self.canvas = FigureCanvasTkAgg(self.fig, self.master)
    self.config_window()
    self.draw_graph_one()
    self.frame.pack(expand=YES, fill=BOTH)

    def config_window(self):
    self.canvas.mpl_connect("key_press_event", self.on_key_press)
    toolbar = NavigationToolbar2Tk(self.canvas, self.master)
    toolbar.update()
    self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
    self.button = Button(self.master, text="Quit", command=self._quit)
    self.button.pack(side=BOTTOM)
    self.button_switch = Button(self.master, text="Switch Graphs", command=self.switch_graphs)
    self.button_switch.pack(side=BOTTOM)

    def plot_data(self):
    def func3(x, y):
    return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-(x ** 2 + y ** 2))
    dx, dy = 0.05, 0.05
    x = np.arange(-3.0, 3.0, dx)
    y = np.arange(-3.0, 3.0, dy)
    X, Y = np.meshgrid(x, y)
    self.extent = np.min(x), np.max(x), np.min(y), np.max(y)
    self.Z1 = np.add.outer(range(8), range(8)) % 2 # chessboard
    self.Z2 = func3(X, Y)

    def draw_graph_one(self):
    self.plot_data()
    self.ax.remove()
    self.ax = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
    extent=self.extent)
    self.canvas.draw()

    def draw_graph_two(self):
    self.plot_data()
    self.ax.remove()
    self.ax = plt.subplot(1, 2, 1)
    self.ax = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
    extent=self.extent)
    self.ax = plt.subplot(1, 2, 2)
    self.a = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
    extent=self.extent)
    self.b = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
    extent=self.extent)
    self.canvas.draw()

    plt.subplots_adjust(left=0.15, bottom=0.15)
    slider_ax = plt.axes([0.06, 0.25, 0.0225, 0.5])

    alfa_slider = Slider(slider_ax,
    label="Transparency",
    valmin=0,
    valmax=1,
    valinit=0,
    orientation="vertical"
    )

    alfa_slider.on_changed(self.update_slider)
    rax = plt.axes([0.06, 0.05, 0.15, 0.15])
    radio = RadioButtons(rax, ('Reds', 'Greens', 'Blues', 'Oranges', 'Wistia', 'plasma', 'inferno'), active=0)
    radio.on_clicked(self.update_radio)
    self.canvas.draw()

    def update_slider(self,alpha_):
    self.b.set_alpha(alpha_)
    self.canvas.draw()

    def update_radio(self,label_):
    self.b.set_cmap(label_)
    self.canvas.draw()

    def on_key_press(self,event,toolbar):
    print("you pressed {}".format(event.key))
    key_press_handler(event, self.canvas, toolbar)

    def _quit(self):
    self.master.quit() # stops mainloop

    def switch_graphs(self):
    # Need to call the correct draw, whether we're on graph one or two
    self.graphIndex = (self.graphIndex + 1) % 2
    if self.graphIndex == 0:
    self.draw_graph_one()
    else:
    self.draw_graph_two()


    def main():
    root = Tk()
    matplotlibSwitchGraphs(root)
    root.mainloop()


    if __name__ == '__main__':
    main()
    我试图在函数内部输入 update_slider 和 update_radio 函数,但我不能使用 self.canvas.draw()。
    此外 .remove() 和 .cla() 不会清除窗口。
    以下是我想切换的图表 View :
    enter image description here
    enter image description here

    最佳答案

    首先回答你的最后一个问题,你的大问题是你试图用一个数字来显示两个单独的图形,而不了解 pyplot 的实际工作原理。这样做是可能的,正如我将在下面概述的那样,但是当您在它们之间切换时,您对图表所做的任何修改都会丢失。我建议阅读 working with multiple axes and figures section of the pyplot tutorial .在 MATLAB 和 pyplot 中的关键要点是,所有绘图函数都应用于最后一个图形和轴。
    当您拨打 self.draw_graph_two() ,您创建的最后一个轴是 RadioButtons .因此,pyplot 将这些轴作为当前轴。当您拨打 self.draw_graph_one() 时第二次(第一次是在您初始化时),它在当前图形和当前轴上绘制图,其中 RadioButtons是。
    要解决此问题,请调用 plt.clf()作为draw_graph_one的第一行和 draw_graph_two , 在尝试绘制新图形之前。这会清除图形,允许从头开始绘制新图(这是您的两个绘制函数所做的)。这允许您在两个绘图之间连续切换,尽管每次切换绘图都会被清除并且对绘图的任何修改都会丢失。您也可以删除 self.ax.remove()行,因为它们会导致错误并且不需要。
    对于前两个问题,可以通过阅读 RadioButtons 的文档来回答这些问题。和 Slider here .您必须保留对小部件的引用,以便它们保持响应。所以修改你的 draw_graph_two返回 alfa_sliderradio使这些小部件保持响应。或者,将它们声明为实例变量也会保留一个引用( self.alfa_sliderself.radio )。
    所以你的工作图表查看器是:

    import matplotlib
    import tkinter as tk
    matplotlib.use("TkAgg")
    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
    from matplotlib.backend_bases import key_press_handler
    from matplotlib.widgets import Slider, RadioButtons

    # Seperated out config of plot to just do it once
    def config_plot():
    fig, ax = plt.subplots()
    ax.set(xlabel='time (s)', ylabel='voltage (mV)',
    title='Graph One')
    return (fig, ax)


    class matplotlibSwitchGraphs:
    def __init__(self, master):
    self.master = master
    self.frame = tk.Frame(self.master)
    self.fig, self.ax = config_plot()
    self.graphIndex = 0
    self.canvas = FigureCanvasTkAgg(self.fig, self.master)
    self.config_window()
    self.plot_data()
    self.draw_graph_one()
    self.frame.pack(expand=True, fill=tk.BOTH)

    def config_window(self):
    self.canvas.mpl_connect("key_press_event", self.on_key_press)
    toolbar = NavigationToolbar2Tk(self.canvas, self.master)
    toolbar.update()
    self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
    self.button = tk.Button(self.master, text="Quit", command=self._quit)
    self.button.pack(side=tk.BOTTOM)
    self.button_switch = tk.Button(self.master, text="Switch Graphs", command=self.switch_graphs)
    self.button_switch.pack(side=tk.BOTTOM)

    def plot_data(self):
    def func3(x, y):
    return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-(x ** 2 + y ** 2))
    dx, dy = 0.05, 0.05
    x = np.arange(-3.0, 3.0, dx)
    y = np.arange(-3.0, 3.0, dy)
    X, Y = np.meshgrid(x, y)
    self.extent = np.min(x), np.max(x), np.min(y), np.max(y)
    self.Z1 = np.add.outer(range(8), range(8)) % 2 # chessboard
    self.Z2 = func3(X, Y)

    def draw_graph_one(self):
    plt.clf()
    self.ax = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
    extent=self.extent)
    self.canvas.draw()

    def draw_graph_two(self):
    plt.clf()
    self.ax = plt.subplot(1, 2, 1)
    self.ax = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
    extent=self.extent)
    self.ax = plt.subplot(1, 2, 2)
    self.a = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
    extent=self.extent)
    self.b = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
    extent=self.extent)
    self.canvas.draw()

    plt.subplots_adjust(left=0.15, bottom=0.15)
    slider_ax = plt.axes([0.06, 0.25, 0.0225, 0.5])

    self.alfa_slider = Slider(slider_ax,
    label="Transparency",
    valmin=0,
    valmax=1,
    valinit=0,
    orientation="vertical"
    )

    self.alfa_slider.on_changed(self.update_slider)
    rax = plt.axes([0.06, 0.05, 0.15, 0.15])
    self.radio = RadioButtons(rax, ('Reds', 'Greens', 'Blues', 'Oranges', 'Wistia', 'plasma', 'inferno'), active=0)
    self.radio.on_clicked(self.update_radio)
    self.canvas.draw()

    def update_slider(self,alpha_):
    self.b.set_alpha(1-alpha_)
    self.canvas.draw()

    def update_radio(self,label_):
    self.b.set_cmap(label_)
    self.canvas.draw()

    def on_key_press(self,event,toolbar):
    print("you pressed {}".format(event.key))
    key_press_handler(event, self.canvas, toolbar)

    def _quit(self):
    self.master.quit() # stops mainloop

    def switch_graphs(self):
    # Need to call the correct draw, whether we're on graph one or two
    self.graphIndex = (self.graphIndex + 1) % 2
    if self.graphIndex == 0:
    self.draw_graph_one()
    else:
    self.draw_graph_two()


    def main():
    root = tk.Tk()
    matplotlibSwitchGraphs(root)
    root.mainloop()


    if __name__ == '__main__':
    main()
    注意我还做了一些其他的轻微修改。不要使用 from tkinter import * ,您已经在上面导入并使用 import *是个坏习惯。我反转了滑块以使透明度有意义。 self.plot_data()仅在 __init__ 中调用一次因为它不会改变。

    关于python - 如何在两个图形之间切换并保持单选按钮和 slider 更新工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68931326/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com