hello I would like to call a function in the root window from a Toplevel window. I want to create new tabs in the first window from a preference window (with parameters) But i recieve an error code :
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3312.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\mircirc\gui_preferences.py", line 12, in add_tab
master.new_tab()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.3312.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 2354, in __getattr__
return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'new_tab'
What Have i forgotten or not understood ?
Here is my first root window : it's create some tabs and i want to create more tabs from a top level window with the root function new_tab()
from tkinter import ttk
from gui_preferences import *
class GUI_PRINCIPAL():
def __init__(self):
salons = ["#Radio-Evasion", "#un-autre-regard"]
root = Tk()
notebook = ttk.Notebook(root)
ttk.Frame(notebook)
root.title("Principale")
def ouvre_gui_preferences():
GUI_PREFERENCES(root)
def do_something():
print("Menu clicked")
def create_menu_bar(self):
menu_bar = Menu(self)
menu_file = Menu(menu_bar, tearoff=0)
menu_file.add_command(label="New", command=do_something)
menu_file.add_command(label="Save", command=do_something)
menu_file.add_separator()
menu_file.add_command(label="Preferences", command=ouvre_gui_preferences)
menu_file.add_separator()
menu_file.add_command(label="Exit", command=self.quit)
menu_bar.add_cascade(label="File", menu=menu_file)
menu_outils = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Outils", menu=menu_outils)
# menu_outils.add_command(label="Annonces", command=ouvre_annonces)
menu_outils.add_command(label="!cmd", command=ouvre_gui_preferences)
menu_help = Menu(menu_bar, tearoff=0)
menu_help.add_command(label="About", command=do_something)
menu_bar.add_cascade(label="Help", menu=menu_help)
self.config(menu=menu_bar)
def add_tab(tab_text):
tab_name = Frame(notebook)
notebook.add(tab_name, text="{}".format(tab_text))
def new_tab():
tab_name = Frame(notebook)
notebook.add(tab_name, text="{}".format("tab_text"))
# creation Menu
create_menu_bar(root)
# Création des Tabs salons
for i, salon in enumerate(salons):
add_tab(salons[i])
notebook.pack(expand=True, fill="both")
root.mainloop()
gui = GUI_PRINCIPAL()
Here is my TopLevel window
from tkinter import *
from tkinter.ttk import *
class GUI_PREFERENCES(Toplevel):
def __init__(self, master=None, irc=None):
super().__init__(master=master)
self.title("Preferences")
self.geometry(" 90 90")
def add_tab():
master.new_tab()
self.btn_add = Button(self, text="Append tab", state='normal', command=add_tab)
self.btn_add.grid(row=1, column=0, padx=(5, 0))v
CodePudding user response:
Issues
- Currently, your
new_tab()
function is a local function known to only the members sitting inside the__init__
method ofGUI_PRINCIPAL
. - A function sitting in
GUI_PRINCIPAL
can't be accessed by the toplevel because you are passing theGUI_PRINCIPAL.root
as master to the toplevel. And thetk.Tk
object doesn't have anew_tab
function.
Fixes
- Move the functions out of
__init__
method ofGUI_PRINCIPAL
- You can make the
GUI_PRINCIPAL
class inherit fromtk.Tk
and then it would be a lot easier to do or you can take theGUI_PRINCIPAL
as an argument with the master argument in the toplevel class.
Following some naming conventions may make the code look cleaner, but thats left to you.
Complete Code
With all the fixes applied, your code should look like following
# try not to import globally
import tkinter as tk
from tkinter import ttk
class Preferences(tk.Toplevel):
def __init__(self, master, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.master = master
self.title("Preferences")
self.geometry(" 90 90")
def add_tab():
master.new_tab()
self.btn_add = tk.Button(self, text="Append tab", state='normal', command=add_tab)
self.btn_add.grid(row=1, column=0, padx=(5, 0))
class Principal(tk.Tk):
def __init__(self, master=None, *args, **kwargs):
super().__init__(master, *args, **kwargs)
self.title("Principale")
salons = ["#Radio-Evasion", "#un-autre-regard"]
self.notebook = ttk.Notebook(self)
ttk.Frame(self.notebook)
# creation Menu
self.create_menu_bar()
# Création des Tabs salons
for i, salon in enumerate(salons):
self.add_tab(salons[i])
self.notebook.pack(expand=True, fill="both")
def ouvre_gui_preferences(self):
Preferences(self)
def do_something(self):
print("Menu clicked")
def create_menu_bar(self):
menu_bar = tk.Menu(self)
menu_file = tk.Menu(menu_bar, tearoff=0)
menu_file.add_command(label="New", command=self.do_something)
menu_file.add_command(label="Save", command=self.do_something)
menu_file.add_separator()
menu_file.add_command(label="Preferences", command=self.ouvre_gui_preferences)
menu_file.add_separator()
menu_file.add_command(label="Exit", command=self.quit)
menu_bar.add_cascade(label="File", menu=menu_file)
menu_outils = tk.Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Outils", menu=menu_outils)
# menu_outils.add_command(label="Annonces", command=ouvre_annonces)
menu_outils.add_command(label="!cmd", command=self.ouvre_gui_preferences)
menu_help = tk.Menu(menu_bar, tearoff=0)
menu_help.add_command(label="About", command=self.do_something)
menu_bar.add_cascade(label="Help", menu=menu_help)
self.config(menu=menu_bar)
def add_tab(self, tab_text):
tab_name = tk.Frame(self.notebook)
self.notebook.add(tab_name, text="{}".format(tab_text))
def new_tab(self):
tab_name = tk.Frame(self.notebook)
self.notebook.add(tab_name, text="{}".format("tab_text"))
root = Principal()
root.mainloop()