Alex Rivera | Logout

Tkinter - RuntimeError: maximum recursion depth exceeded

Asked 2012-04-06T05:24:01.097
8

I started programming in Python on Monday. I have enjoyed learning it. But I am stuck trying to understand how to avoid recursion when switching between tkinter menus! I am sure this is a very basic question, and I appreciate you tolerating my ignorance on this subject, but I have been unable to find an answer elsewhere.

What I am now doing is, eventually, giving me the error: RuntimeError: maximum recursion depth exceeded while calling a Python object

This is the pattern I am currently using. UPDATED: The code below is now a full, isolated copy reproducing the problem I am facing! :D

from tkinter import *

def mainmenu():
    global frame, root

    frame.destroy()

    frame = Frame()
    frame.pack()

    button1 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)
    button2 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)
    button3 = Button(frame, text="mainmenu", command = mainmenu)

    button1.pack(side=LEFT)
    button2.pack(side=LEFT)
    button3.pack(side=LEFT)

    root.mainloop()

def anothermenulikethis():
    global frame, root

    frame.destroy()

    frame = Frame()
    frame.pack()

    button1 = Button(frame, text="mainmenu", command = mainmenu)
    button2 = Button(frame, text="mainmenu", command = mainmenu)
    button3 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)

    button1.pack(side=LEFT)
    button2.pack(side=LEFT)
    button3.pack(side=LEFT)

    root.mainloop()

root = Tk()
root.title("Recursive Menu Problem Isolation")
root.geometry("1200x600")
frame = Frame()

mainmenu()

And it all works fine, until its inevitable failure from maximum recursion depth. If anyone can suggest a better way of doing things, or has a link to an example of a better way of doing this, I am eager to learn.

PS: I have looked at and tried increasing the recursion depth, but I feel that is a poor man's solution to what

Edit
Report

1 Answer

13

Only one mainloop() is needed to handle a tkinter GUI.

With that said, I think you just need an example of the class structure:

from tkinter import Tk,Button

class Application(Tk):

    def say_hi(self):
        print('Hello world?!')

    def close_app(self):
        self.destroy()

    def create_Widgets(self):
        self.quitButton = Button(self, width=12, text='Quit', bg='tan',
                    command=self.close_app)
        self.quitButton.grid(row=0, column=0, padx=8, pady=8)

        self.helloButton = Button(self, width=12, text='Hello',
                    command=self.say_hi)
        self.helloButton.grid(row=0, column=1, padx=8, pady=8)

    def __init__(self):
        Tk.__init__(self)
        self.title('Hello world!')
        self.create_Widgets()

app = Application()
app.mainloop()

To avoid possible conflicts with other modules, some people prefer importing like this
(clearly stating where everything comes from):

import tkinter as tk

class Application(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title('Hello world!')

        self.quitButton = tk.Button(self, width=12, text='Quit', bg='tan',
                    command=self.close_app)
        self.quitButton.grid(row=0, column=0, padx=8, pady=8)

        self.helloButton = tk.Button(self, width=12, text='Hello',
                    command=self.say_hi)
        self.helloButton.grid(row=0, column=1, padx=8, pady=8)

    def say_hi(self):
        print('Hello world?!')

    def close_app(self):
        self.destroy()

app = Application()
app.mainloop()

And as you can see, creating the widgets can easily happen in the __init__


I decided to make a more practical / educational example based on what I've learned in the past month. While doing so I had a bit of a revelation: not everything requires a self. prefix in a class! This is especially true

answered 2012-04-06T05:51:21.297

Your Answer