tkinter 从顶层调用根函数 window

tkinter call a root function from a toplevel window

你好,我想从 Toplevel window 调用根 window 中的函数。 我想根据首选项 window(带参数)在第一个 window 中创建新标签 但我收到错误代码:

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'

我忘了或没听懂什么?

这是我的第一个根window: 它创建了一些标签 我想使用根函数 new_tab()

从顶层 window 创建更多选项卡
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()

这是我的顶级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

问题

  • 目前,您的 new_tab() 函数是一个局部函数,只有位于 GUI_PRINCIPAL__init__ 方法内的成员知道。
  • 顶层无法访问位于 GUI_PRINCIPAL 中的函数,因为您将 GUI_PRINCIPAL.root 作为主函数传递给顶层。 tk.Tk 对象没有 new_tab 函数。

修复

  • 将函数从 GUI_PRINCIPAL
  • __init__ 方法中移出
  • 你可以让 GUI_PRINCIPAL class 继承自 tk.Tk 然后它会更容易做到 或者 你可以采取GUI_PRINCIPAL 作为顶层主参数的参数 class.

遵循一些命名约定可能会使代码看起来更简洁,但这留给你了。

完整代码

应用所有修复后,您的代码应如下所示

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