Нажатие кнопки не возвращает объект Line2D в Tkinter - PullRequest
1 голос
/ 22 января 2020

Я работаю с matplotlib и tkinter, чтобы создать программу, которая может строить графики с помощью matplotlib, и мы можем взаимодействовать с графиками с помощью кнопок (созданных с помощью Tkinter). У меня есть кнопка с именем 'Line', которая управляет поведением Line2D объект уже создан matplotlib. Но я не могу вызвать объект Line2D с помощью аргумента ключевого слова command= виджета кнопки.

Очень простой рабочий пример:

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, я могу управлять его атрибутами с помощью кнопки.

1 Ответ

1 голос
/ 22 января 2020

Вам необходимо понять, в каком контексте оценивается лямбда-функция. В этом контексте 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. Это неловкий стиль. Вместо этого вы можете использовать словарь, который отображает строки на объекты, если это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...