【问题标题】:Button press not returning Line2D object in Tkinter按钮按下不返回 Tkinter 中的 Line2D 对象
【发布时间】:2020-01-22 19:53:15
【问题描述】:

我正在使用 matplotlib 和 tkinter 创建一个程序,该程序可以使用 matplotlib 绘制图形,我们可以使用按钮(使用 Tkinter 创建)与图形交互。我有一个名为“Line”的按钮,它操纵 Line2D 的行为matplotlib 已经创建的对象。但我无法使用按钮小部件的command= 关键字参数调用 Line2D 对象。

一个非常简单的工作示例是:

from matplotlib import pyplot as plt

squares = [i**2 for i in range(-10, 10)]

fig = plt.figure()
ax = fig.add_subplot(111)

line1 = ax.plot(squares)
print(eval('line1'))
plt.show()

打印命令print(eval('line1'))的输出如预期:

[<matplotlib.lines.Line2D object at 0x000002BF273FEF48>]

但如果我使用以下代码,以同样的方式:

from tkinter import *
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure


class App:
    def __init__(self, master):

        frameA = Frame(master)

        fig = Figure()
        ax = fig.add_subplot(111)

        canvas = FigureCanvasTkAgg(fig, master=frameA)
        canvas.get_tk_widget().pack(side='top', fill='both', expand=1)

        line1 = ax.plot(squares)
        plt.show()

        frameB = Frame(master)
        buttonA = Button(frameB, text="line1", height=20, width=50, command=lambda: print(eval(buttonA.cget('text'))))

        buttonA.pack(side="top")

        frameA.grid(row=0, column=0)
        frameB.grid(row=0, column=1)


squares = [i**2 for i in range(-10,10)]

root = Tk()
MyApp = App(root)
root.mainloop()

command=lambda: print(eval(buttonA.cget('text'))) 部分而不是返回 Line2D 对象会产生错误。 为了简单起见,我使用print() 函数,所以一旦我可以成功调用 Line2D 对象,我就可以使用按钮来操作它的属性。

【问题讨论】:

  • 你为什么写eval('line1') 而不是line1?你的代码完全不需要eval()
  • @jasonharper 我将制作其他十几个按钮(使用 for 循环),每个按钮都将连接到它自己对应的绘图。我看到的唯一连接是将按钮的文本值设置为绘图的名称,从而通过 eval 函数调用绘图。

标签: python python-3.x matplotlib tkinter


【解决方案1】:

您需要了解计算 lambda 函数的上下文。在这种情况下,line1 不再作为变量存在。

这是一个选项:

from tkinter import *
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

class App:
    def __init__(self, master):

        frameA = Frame(master)

        fig = Figure()
        ax = fig.add_subplot(111)

        canvas = FigureCanvasTkAgg(fig, master=frameA)
        canvas.get_tk_widget().pack(side='top', fill='both', expand=1)

        self.line1 = ax.plot(squares)

        frameB = Frame(master)
        self.buttonA = Button(frameB, text="self.line1", height=20, width=50, 
                         command=self.func)

        self.buttonA.pack(side="top")

        frameA.grid(row=0, column=0)
        frameB.grid(row=0, column=1)

    def func(self):
        print(eval(self.buttonA.cget('text')))


squares = [i**2 for i in range(-10,10)]

root = Tk()
MyApp = App(root)
root.mainloop()

请考虑不要使用eval。这是尴尬的风格。相反,如果需要,您可以使用将字符串映射到对象的字典。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-24
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-17
    相关资源
    最近更新 更多