如何通过Tkinter按钮功能传递数据,lambda问题

时间:2019-01-09 05:45:36

标签: python tkinter lambda tkinter-canvas

起始页有两个按钮:在新框中提取数据和绘制数据。图(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) 

问题:我想绘制的数据正在通过动画正确执行。我可以在命令提示符下看到数据。会弹出新的tkinter窗口,但不会绘制从“动画”生成的任何数据。

如果我从Button 2删除了LAMBDA,我会在新框架中看到正确的图,但是这不是我将来如何构造代码的方式。我无法删除lambda,因为最终将像Button 2一样会有30个按钮。

按钮2中的LAMBDA怎么了?

1 个答案:

答案 0 :(得分:0)

  

按钮2中的LAMBDA怎么了?

tkinter.Button中的command parameter需要对函数的引用。

lambda是创建anonymous, simple function的语法。它的语法实际上与函数签名相同。

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在新框架中显示图形[...]

     

如果我从按钮2中删除了LAMBDA,我会在新框架中看到正确的图

在执行代码以配置lambda而不是创建匿名函数时,删除animate(3)关键字将立即执行button2。然后将button2的命令设置为animate(3)返回的值。如果无法调用,则将其有效地忽略。

由于您没有为animatecontroller.show_page提供可行的代码,因此我们每个人都无法确定它的作用,但是从结果中可以安全地假设{{ 1}}将animate存储在属性/变量中,然后figure(或controller.show_page的未提供部分)从该属性/变量中检索PageTwo 。这就是为什么代码似乎仍然有效的原因:因为仅存储一个figurefigure将始终检索正确的数字。如果您有多个按钮,则无论按下哪个按钮,button1总是会显示最后创建的按钮button1,因为这是最近存储的figure

很明显,所有这些问题的中心可能是figure如何存储animate以及figure / controller.show_page检索图形的方式。两种概括的解释:

  • PageTwo初始化之后或之中创建了与PageOne交互(和/或影响figure实例化)的事物。 使用 PageTwo,此对象在创建时具有一定的值,直到该对象完成其过程(无论是初始化,调用后续方法,设置第三变量,等等)。 如果没有 lambda,将立即调用lambda,它会更改此对象以反映animate的创建。
  • 变量集figure或另一个中间变量正在被垃圾回收,因为您没有维护对其的引用。

由于我认为第一个可能性更高,因此我将特别选择figurea作为候选:这两个变量都不是方法参数(而且它们似乎都不是从方法中提取的) f,根据您的代码),因此它们是可以在更高范围内执行期间轻松更改的引用。

如果您reduce your code to a MVCE,则可以更清楚地了解问题所在。在编写MVCE时,您可能还会发现问题消失了,这将告诉您确切的错误原因,并让您立即解决问题,而不用等待堆栈溢出的答案。