Tkinter – RuntimeError: превышена максимальная глубина рекурсии

Я начал программировать на Python в понедельник. Мне понравилось изучать его. Но я застреваю, пытаясь понять, как избежать рекурсии при переключении между меню tkinter! Я уверен, что это очень простой вопрос, и я ценю, что вы терпите мое невежество по этому вопросу, но я не смог найти ответ в другом месте.

То, что я сейчас делаю, в конечном итоге дает мне ошибку: RuntimeError: максимальная глубина рекурсии превышена при вызове объекта Python

Это образец, который я использую в настоящее время. ОБНОВЛЕНО: приведенный ниже код теперь представляет собой полную изолированную копию, воспроизводящую проблему, с которой я сталкиваюсь! : 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() 

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

PS: Я посмотрел и попытался увеличить глубину рекурсии, но я чувствую, что это решение бедного человека, что является фундаментальной проблемой моего подхода.

Спасибо заранее, всем.

В соответствии с запросом, вот слежение:

 Exception in Tkinter callback Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1399, in __call__ return self.func(*args) File "/Users/diligentstudent/Desktop/menutest.py", line 11, in mainmenu button1 = Button(frame, text="anothermenulikethis", command = anothermenulikethis) File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 2028, in __init__ Widget.__init__(self, master, 'button', cnf, kw) File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1958, in __init__ (widgetName, self._w) + extra + self._options(cnf)) File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1043, in _options v = self._register(v) File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1079, in _register f = CallWrapper(func, subst, self).__call__ RuntimeError: maximum recursion depth exceeded 

One Solution collect form web for “Tkinter – RuntimeError: превышена максимальная глубина рекурсии”

Для обработки графического интерфейса tkinter требуется только один mainloop() .

С учетом сказанного, я думаю, вам просто нужен пример структуры класса:

 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() 

Чтобы избежать возможных конфликтов с другими модулями, некоторые люди предпочитают импортировать как это
(четко указывая, откуда все исходит):

 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() 

И, как видите, создание виджетов может легко произойти в __init__


Я решил сделать более практичный / образовательный пример, основанный на том, что я узнал за последний месяц. При этом у меня было немного откровения: не все требует самости. префикс в классе! Это особенно верно для класса tkinter, потому что вы не манипулируете им как объект в основной программе. В основном вам нужно «я». префикс, когда вы собираетесь использовать что-то в методе позже. В предыдущих примерах показано, как что-либо (например, кнопки) может получить сам. префикс, даже если это совершенно не нужно.

Некоторые примеры этого примера показывают:

pack() и grid() могут использоваться в том же графическом интерфейсе, если они не делят мастер.

• Можно изменять текстовый виджет, чтобы не расширяться при изменении размера шрифта.

• Как включить или отключить выделенный текст.

• Как по-настоящему центрировать графический интерфейс на экране. (дополнительная информация здесь)

• Как создать окно Toplevel в том же месте, что и в главном окне.

• Два способа предотвратить удаление окна Toplevel, поэтому его нужно только создать.

• Правильно сделайте функцию ctrl + a (выберите все).

 import tkinter as tk import tkFont class Application(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.title('T-Pad') # Menubar menubar = tk.Menu(self) filemenu = tk.Menu(menubar, tearoff=0) filemenu.add_command(label="Exit", command=self.close_app) menubar.add_cascade(label="File", menu=filemenu) formatmenu = tk.Menu(menubar, tearoff=0) formatmenu.add_command(label="Font", command=self.show_sizeWin) menubar.add_cascade(label="Format", menu=formatmenu) self.config(menu=menubar) # Bold Button boldButton = tk.Button(self, width=12, text='Bold', command=self.make_bold) boldButton.pack() # Text widget, its font and frame self.defaultFont = tkFont.Font(name="defFont") textFrame = tk.Frame(self, borderwidth=1, relief="sunken", width=600, height=600) textFrame.grid_propagate(False) # ensures a consistent GUI size textFrame.pack(side="bottom", fill="both", expand=True) self.mText = tk.Text(textFrame, width=48, height=24, wrap='word', font="defFont") self.mText.grid(row=0, column=0, sticky="nsew") # Scrollbar and config tScrollbar = tk.Scrollbar(textFrame, command=self.mText.yview) tScrollbar.grid(row=0, column=1, sticky='nsew', pady=1) self.mText.config(yscrollcommand=tScrollbar.set) # Stretchable textFrame.grid_rowconfigure(0, weight=1) textFrame.grid_columnconfigure(0, weight=1) # Bold Tag self.bold_font = tkFont.Font(self.mText, self.mText.cget("font")) self.bold_font.configure(weight="bold") self.mText.tag_configure("bt", font=self.bold_font) # Center main window self.update_idletasks() xp = (self.winfo_screenwidth() / 2) - (self.winfo_width() / 2) - 8 yp = (self.winfo_screenheight() / 2) - (self.winfo_height() / 2) - 30 self.geometry('{0}x{1}+{2}+{3}'.format(self.winfo_width(), self.winfo_height(), xp, yp)) # Font Size Window (notice that self.sizeWin is given an alias) sizeWin = self.sizeWin = tk.Toplevel(self, bd=4, relief='ridge') self.sizeList = tk.Listbox(sizeWin, width=10, height=17, bd=4, font=("Times", "16"), relief='sunken') self.sizeList.grid() doneButton = tk.Button(sizeWin, text='Done', command=sizeWin.withdraw) doneButton.grid() for num in range(8,25): self.sizeList.insert('end', num) sizeWin.withdraw() sizeWin.overrideredirect(True) # No outerframe! # Below is another way to prevent a TopLevel window from being destroyed. # sizeWin.protocol("WM_DELETE_WINDOW", self.callback) # Bindings # Double click a font size in the Listbox self.sizeList.bind("<Double-Button-1>", self.choose_size) self.bind_class("Text", "<Control-a>", self.select_all) ## def callback(self): ## self.sizeWin.withdraw() def select_all(self, event): self.mText.tag_add("sel","1.0","end-1c") def choose_size(self, event=None): size_retrieved = self.sizeList.get('active') self.defaultFont.configure(size=size_retrieved) self.bold_font.configure(size=size_retrieved) def show_sizeWin(self): self.sizeWin.deiconify() xpos = self.winfo_rootx() - self.sizeWin.winfo_width() - 8 ypos = self.winfo_rooty() self.sizeWin.geometry('{0}x{1}+{2}+{3}'.format(self.sizeWin.winfo_width(), self.sizeWin.winfo_height(), xpos, ypos)) def make_bold(self): try: current_tags = self.mText.tag_names("sel.first") if "bt" in current_tags: self.mText.tag_remove("bt", "sel.first", "sel.last") else: self.mText.tag_add("bt", "sel.first", "sel.last") except tk.TclError: pass def close_app(self): self.destroy() app = Application() app.mainloop() 
  • Как обновить содержимое FigureCanvasTkAgg
  • Вставка gif изображения в холст с помощью Tkinter
  • Как я могу периодически менять изображение tkinter?
  • Как установить порядок вкладок в приложении tkinter?
  • python tkinter overrideredirect; не может получать нажатия клавиш (Linux)
  • Справка с событием <key> в python Виджет ввода
  • Невозможно изменить размер изображения с помощью tkinter
  • Прозрачный фон окна (Python Tkinter)
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.