带有菜单栏命令的 Tkinter 无意递归......原因? [英] Tkinter unintentional recursion with menu bar command...cause?

查看:28
本文介绍了带有菜单栏命令的 Tkinter 无意递归......原因?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 tkinter 制作 Python GUI,我需要一个菜单​​项来打开主窗口的另一个副本.我试着做下面的代码,当我运行程序时,它冻结了一点,然后打开了大量的窗口.打印的最后一条错误消息如下.

I'm trying to make a Python GUI using tkinter, and I need a menu item that opens another copy of the main window. I tried to do the following code, and when I ran the program, it froze for a bit, then opened a large number of windows. The last error message printed is below.

我有两个问题.

  1. 如何完成使新建"按钮打开一个新窗口和 TheThing 类实例的任务?(在 IDLE 中,File > New File 具有我正在寻找的行为.)
  2. 为什么会发生这个错误?

  1. How can I accomplish the task of making the "New" button open a new window and instance of the TheThing class? (In IDLE, File > New File has the behavior I'm seeking.)
  2. Why is this error happening?

RecursionError: maximum recursion depth exceeded while calling a Python object

我的代码:

import tkinter as tk

class TheThing:
    def __init__(self, root):
        root.option_add('*tearOff', False)

        menubar = tk.Menu(root)
        root.config(menu = menubar)

        file = tk.Menu(menubar)
        menubar.add_cascade(menu = file, label = "File")
        file.add_command(label = 'New', command = doathing())

def doathing():
    thing1 = tk.Tk()
    thing2 = TheThing(thing1)

def main():
    win = tk.Tk()
    do = TheThing(win)
    win.mainloop()

if __name__ == '__main__': main()

我已经寻找答案的地方:

Places I've already looked for answers:

  • 这个问题似乎有一个非常相似的问题.我也许可以研究一下并找到解决方案,但我仍然无法理解问题所在.

  • This question seemed like it was having a very similar problem. I may be able to study that and find a solution, but I still won't understand the problem.

这个问题是关于递归、python 和 tkinter,但似乎更多的是 after 的事情.

This question was about recursion, python, and tkinter, but seemed to be about more the after thing.

推荐答案

问题出在这一行:

    file.add_command(label = 'New', command = doathing())

在这里,您执行doathing 回调,然后尝试将其结果(None)绑定到命令.在这种特定情况下,这也会导致无限递归,因为回调将创建帧的新实例,该实例将再次执行回调,这将创建另一个帧,依此类推.您必须将函数本身绑定到命令,而不是调用该函数.

Here, you execute the doathing callback and then try to bind its result (which is None) to the command. In this specific case, this also leads to an infinite recursion, as the callback will create a new instance of the frame, which will again execute the callback, which will create another frame, and so on. Instead of calling the function, you have to bind the function itself to the command.

    file.add_command(label = 'New', command = doathing)  # no ()

如果您需要将参数传递给该函数(这里不是这种情况),您可以使用 lambda:

In case you need to pass parameters to that function (not the case here) you can use a lambda:

    file.add_command(label = 'New', command = lambda: doathing(params))

<小时>

此外,与其创建另一个 Tk 实例,不如创建一个 Toplevel 回调中的实例,即


Also, instead of creating another Tk instance you should probably just create a Toplevel instance in the callback, i.e.

def doathing():
    thing1 = tk.Toplevel()
    thing2 = TheThing(thing1)

这篇关于带有菜单栏命令的 Tkinter 无意递归......原因?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆