Как передать данные через функцию кнопки Tkinter, проблемы с лямбдой - PullRequest
0 голосов
/ 09 января 2019

Стартовая страница имеет две кнопки: вытащить данные и вывести данные в новом кадре. цифра (f, a) была определена, но не включена в приведенный ниже фрагмент кода:

 button1 = ttk.Button(self, text="Show Graph",
                            command=lambda: controller.show_frame(PageTwo))
 button1.pack()

 button2 = ttk.Button(self, text="PL3",
                            command=lambda: animate(3)) 
 button2.pack()

Button2 запускает функцию «animate», принимаемую в качестве аргумента (J), извлекает данные, соответствующие J, затем строит график рассеяния.

def animate(j)
   a.plot(Date, Left,"go", label = "price")
   title = "Left Fid"
   a.set_title(title) 

Button1 затем показывает рисунок в новом кадре

class PageTwo(tk.Frame):
def __init__(self, parent, controller):
    tk.Frame.__init__(self, parent)
    label = tk.Label(self, text="Graph page", font=LARGE_FONT)
    label.pack(pady=10,padx=10)


    button1 = ttk.Button(self, text="back to home",
                        command=lambda: controller.show_frame(StartPage))
    button1.pack()

    canvas = FigureCanvasTkAgg(f,self)
    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand = True)

    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand = True) 

Проблема: данные, которые я хочу получить, корректно выполняются animate. Я могу увидеть данные в командной строке. Появляется новое окно tkinter, но без отображения каких-либо данных, сгенерированных из «animate».

Если я удаляю LAMBDA из кнопки 2, я вижу правильный график в новом кадре, но я не хочу структурировать код на будущее. Я не могу удалить лямбду, потому что в конце концов будет 30 кнопок, как кнопка 2.

Что происходит с LAMBDA в кнопке 2?

1 Ответ

0 голосов
/ 11 января 2019

Что происходит с LAMBDA в кнопке 2?

Параметр команды в tkinter.Button ожидает ссылки на функцию.

lambda - это синтаксис для создания анонимной простой функции . Его синтаксис практически идентичен сигнатуре функции.

def func(a, *args, b = 2, **kwargs):
    return a+b
func = lambda a, *args, b = 2, **kwargs: a+b

Поскольку lambda является простым способом создания функции, люди часто используют ее в tkinter для объединения функций с предопределенными аргументами, специфичными для данного обратного вызова / команды.

Button2 запускает функцию «animate», принимаемую в качестве аргумента (J), получает данные, соответствующие J, затем строит график рассеяния. [...]

Button1 затем показывает фигуру в новом кадре [...]

Если я удаляю LAMBDA из кнопки 2, я вижу правильный график в новом кадре

При удалении ключевого слова lambda animate(3) выполняется сразу же, когда выполняется код для настройки button2 вместо создания анонимной функции. Команда для button2 затем устанавливается на то, что animate(3) возвращает. Если он не вызывается, то он фактически игнорируется.

Поскольку вы не предоставили работоспособный код для animate или controller.show_page, никто из нас не может точно знать, что он делает, но на основании результатов можно предположить, что animate хранит figure в атрибуте / переменной, а затем controller.show_page (или некоторая часть PageTwo, которая не указана) извлекает figure из этого атрибута / переменной. Вот почему код , по-видимому, все еще работает: поскольку при сохранении только одного figure, button1 всегда будет получать правильную цифру. Если бы у вас было несколько кнопок, предположительно, button1 всегда отображал бы figure для последней созданной кнопки независимо от того, какая кнопка была нажата, поскольку это самая последняя сохраненная figure.

.

Очевидно, проблема в центре всего этого, вероятно, заключается в том, как animate хранит figure и как controller.show_page / PageTwo извлекает фигуру. Два обобщенных объяснения:

  • Нечто создается после или во время инициализации PageOne, которое взаимодействует с figure (и / или влияет на создание PageTwo). При lambda этот объект при создании имеет определенное значение, которое не изменяется до тех пор, пока объект не завершит свой процесс (будь то инициализация, вызов последующего метода, установка третичной переменной и т. Д.). Без lambda, animate вызывается немедленно, что изменяет этот объект, чтобы отразить создание figure.
  • Переменная корпус figure или другая промежуточная переменная собирается мусором, потому что вы не ведете ссылку на нее.

Так как я думаю, что первое более вероятно, я специально выберу a и f в качестве кандидатов: ни одна из этих переменных не является параметрами метода (и они, кажется, не извлекаются из controller, в соответствии с вашим кодом), поэтому они являются ссылками, которые могут быть легко изменены во время выполнения в более высоком объеме.

Если вы уменьшите свой код до MVCE , было бы легче понять, в чем именно заключается проблема. Вы также можете обнаружить, что проблема исчезает, когда вы пишете MVCE, который точно скажет вам, что пошло не так, и позволит вам исправить это сразу, а не ждать ответов переполнения стека.

...