Python -向plot的工具栏添加按钮时传递参数(matplotlib)

0wi1tuuw  于 2023-06-30  发布在  Python
关注(0)|答案(2)|浏览(189)

我正在尝试添加一个按钮到toolbar。这个按钮是一个继承了ToolToggleBase的自定义类。在我的自定义SelectButton类中,我想传递几个参数,但我得到一个错误:

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["toolbar"] = "toolmanager"
from matplotlib.backend_tools import ToolToggleBase

def simple_plot(mat):
    fig = plt.figure()
    ax = fig.add_subplot()
    ax.plot(np.reshape(mat, [-1, 1]))
    ax.grid(True)
    ax.legend()
    tm = fig.canvas.manager.toolmanager
    tm.add_tool("CustomButton", SelectButton(fig, ax))
    fig.canvas.manager.toolbar.add_tool(tm.get_tool("CustomButton"), "toolgroup")
    return fig, ax

class SelectButton(ToolToggleBase):
    default_toggled = False

    def __init__(self, fig1, ax1, *args, **kwarg):
        super().__init__(*args, **kwarg)
        print("fig: ", fig1)
        print("ax: ", ax1)

x = [1, 2, 3]
fig, ax = simple_plot(x)
plt.show()

结果:
super().init(*args,**kwargs)TypeError:init()缺少2个必需的位置参数:'toolmanager'和'name'
但是,如果我不传递任何参数,只传递类名,一切都按预期工作:

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["toolbar"] = "toolmanager"
from matplotlib.backend_tools import ToolToggleBase

def simple_plot(mat):
    fig = plt.figure()
    ax = fig.add_subplot()
    ax.plot(np.reshape(mat, [-1, 1]))
    ax.grid(True)
    ax.legend()
    tm = fig.canvas.manager.toolmanager
    tm.add_tool("CustomButton", SelectButton)
    fig.canvas.manager.toolbar.add_tool(tm.get_tool("CustomButton"), "toolgroup")
    return fig, ax

class SelectButton(ToolToggleBase):
    default_toggled = False

    def __init__(self, *args, **kwarg):
        super().__init__(*args, **kwarg)

x = [1, 2, 3]
fig, ax = simple_plot(x)
plt.show()

我知道我必须调用add_tool错误时,使用一个类的示例,而不是类名,但我不明白我应该做什么,如果我想传递参数到SelectButton类。

xfyts7mz

xfyts7mz1#

您需要将类SelectButton本身传递给add_tool,而不是它的示例SelectButton()。您应该将其他参数作为kwargs传递:

def simple_plot(mat):
    fig = plt.figure()
    ax = fig.add_subplot()
    # ...
    tm = fig.canvas.manager.toolmanager
    tm.add_tool("CustomButton", SelectButton, fig=fig, ax=ax)
    fig.canvas.manager.toolbar.add_tool(tm.get_tool("CustomButton"), "toolgroup")
    return fig, ax

class SelectButton(ToolToggleBase):
    default_toggled = False

    def __init__(self, *args, fig, ax, **kwarg):
        super().__init__(*args, **kwarg)
        print("fig: ", fig)
        print("ax: ", ax)

这将打印:

fig:  Figure(640x480)
ax:  Axes(0.125,0.11;0.775x0.77)

如果你出于某种原因真的想使用args而不是kwargs,你应该使用一个partial,如另一个答案所示。只传递前2个参数给super,剩下的自己使用,这是一种技巧而不是解决方案,因为它取决于matplotlib的实现细节:

tm.add_tool("CustomButton", SelectButton, fig, ax)

def __init__(self, *args, **kwarg):
    super().__init__(*args[:2], **kwarg)
    print("fig: ", args[2])
    print("ax: ", args[3])
mdfafbf1

mdfafbf12#

在使用SelectButton类的示例时,您使用的add_tool不正确,从而导致出现当前问题。add_tool方法预期的是类示例,而不是类名的字符串表示形式。
您可以使用lambda函数或分部函数来构建可调用对象,该对象接受必要的参数以将参数传递给SelectButton类。下面是如何更改代码以实现此目的的示例:

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["toolbar"] = "toolmanager"
from matplotlib.backend_tools import ToolToggleBase
from functools import partial

def simple_plot(mat):
    fig = plt.figure()
    ax = fig.add_subplot()
    ax.plot(np.reshape(mat, [-1, 1]))
    ax.grid(True)
    ax.legend()
    tm = fig.canvas.manager.toolmanager
    create_button = partial(SelectButton, fig, ax)
    tm.add_tool("CustomButton", create_button)
    fig.canvas.manager.toolbar.add_tool("CustomButton", "toolgroup")
    return fig, ax

class SelectButton(ToolToggleBase):
    default_toggled = False

    def __init__(self, fig1, ax1, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print("fig:", fig1)
        print("ax:", ax1)

x = [1, 2, 3]
fig, ax = simple_plot(x)
plt.show()

这段代码中的create_button变量被赋予了一个部分函数,该函数接受参数fig和ax,并返回SelectButton类的一个全新示例。然后将工具名称和这个不完整的函数提供给add_tool。
现在,当您执行更改后的代码时,错误应该得到修复,因为SelectButton类现在将正确获取fig和ax参数。

相关问题