破坏tkinter主循环(用画布和按钮),奇怪的行为

2024-04-23 20:13:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我有root=Tk.Tk(),它由标签组成(Tk.标签),参赛表格(Tk.入口),按钮(Tk.按钮)和嵌入的matplotlib FigureCanvasTkAgg。这是一个简单的脚本,它用用户指定的系数(a,b,c)绘制四元函数。但是我在破坏主循环时有一些问题和误解。 我原以为,简单地关闭主窗口(单击右角的“x”)也会导致退出mainloop。我的脚本就是这样,如果我要注释所有与嵌入画布相关的代码。但对于嵌入的FigureCanvasTkAgg,它不会发生(因此需要中断内核以再次运行脚本)。正如在其他questions中所讨论的,有两种退出主循环的方法:root.quit()和{}。所以我也尝试使用这些方法来退出mainloop:

def close_all():
    root.quit()
    root.destroy()

按“新建”按钮:

^{pr2}$

通过覆盖“x”按钮:

root.protocol('WM_DELETE_WINDOW', close_all)

我的问题:

  1. 两种方法都有效。但是为什么如果我只使用root.destroy()root.mainloop()仍然会执行呢?为什么在关闭窗口后mainloop没有被销毁?为什么这个问题会导致FigureCanvasTkAgg? 嵌入matplotlib图的方法如下(如果有助于解释):

    fig, ax = plt.subplots()
    canvas = FigureCanvasTkAgg(fig, master=root)
    plot_widget = canvas.get_tk_widget()
    #(plotting with plt.plot(..))
    canvas.show()
    plot_widget.grid(row=6, column = 0, columnspan=3)
    
  2. close_all()函数在这个意义上起作用,即执行了mainloop的退出,并且脚本执行停止了。但仍有一些奇怪的行为。有一些变量,如var_a = Tk.StringVar(),用于以某种方式从输入字段接收数据:

    L_a = Tk.Label(master=root, width=10, height=2, bd =2, text="a")
    E_a = Tk.Entry(master=root, width=10, bd =2, textvariable=var_a) 
    

    def get_value():
        if not check_if_float(var_a.get()) or not check_if_float(var_b.get()) or not check_if_float(var_c.get()):
            showerror(title = "Error", message = "Invalid entry. Enter integer or decimal numbers, please")
            return None
        a=float(var_a.get())
        b=float(var_b.get())
        c=float(var_c.get())
    

    所以问题和奇怪的行为是,在执行一次代码并关闭主窗口(单击右上角的“x”或单击“Quit”按钮),下一次执行代码将收到空的var_a、var_b、var_c。如果内核中断,代码再次运行,它将正常工作(在jupyter笔记本中运行)。我不知道为什么会这样。


Tags: 方法代码脚本closegetifvarroot
1条回答
网友
1楼 · 发布于 2024-04-23 20:13:24

这是因为没有为变量提供主变量,因此它们默认为创建的第一个Tk()实例,即使它已被销毁。修复方法只是提供正确的根:

var_a = Tk.StringVar(root)

这通常不是问题,因为很少有情况下需要多次调用Tk()。在

相关问题 更多 >