You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter动态生成标签页加载失败求助(附报错)

问题

我有一组可动态变化的标签页名称列表,希望通过循环遍历名称生成对应标签页,并在用户点击不同标签页时展示不同的按钮。但目前标签页无法正常加载,移除绑定的事件命令后,窗口可正常显示正确的标签页。

我的代码:

import tkinter as tk
from tkinter import ttk

def loadtab(event):
    selection = event.widget.select()
    tabN = event.widget.tab(selection, "text")
    t_nos=str(uFrame.index(uFrame.select())+1)
    tab = f'tab{t_nos}'

    if tabN == 'Ed':
        tk.Button(tab, text=tabN).pack()
    elif tabN == 'Ted':
        tk.Button(tab, text=tabN).pack()

root = tk.Tk()
root.title("Tab")

uFrame = ttk.Notebook(root, style="TFrame") #Create notebook
uFrame.pack(pady=20)
uFrame.bind("<<NotebookTabChanged>>", loadtab) #Bind notebook so that when it is changed, it loads items onto each tab

pathOpt = ['Ed', 'Ted'] #Tab names
tNo = 0 #Counter
for name in pathOpt: #parse through tab names and create tabs
    tab = f'tab{tNo + 1}'
    tab = ttk.Frame(uFrame)
    uFrame.add(tab, text=pathOpt[tNo])
    tNo += 1

test = tk.Button(root, text='Deliniate tabs') # placeholder to show where tabs are
test.pack(pady=20)
root.mainloop()

运行报错:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\cwade\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\PyProjects\TemplateTool\TemplateToolV3_Tabs.py", line 12, in loadtab
    tk.Button(tab, text=tabN).pack()
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\cwade\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2707, in __init__
    Widget.__init__(self, master, 'button', cnf, kw)
  File "C:\Users\cwade\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2623, in __init__
    self._setup(master, cnf)
  File "C:\Users\cwade\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2592, in _setup  
    self.tk = master.tk
              ^^^^^^^^^
AttributeError: 'str' object has no attribute 'tk'

我已打印验证标签名称正确,但仍出现上述错误。


解决方案

错误原因

loadtab函数里的tab被赋值成了字符串(比如tab1),但tk.Button的第一个参数要求是tkinter容器对象(比如ttk.Frame),不是字符串。循环创建标签页时,你创建了ttk.Frame对象但没有保存,导致切换时无法拿到正确的容器来放置按钮。

修改后的代码

import tkinter as tk
from tkinter import ttk

# 用字典存储标签页对象,键为标签名称
tab_frames = {}

def loadtab(event):
    selection = event.widget.select()
    tabN = event.widget.tab(selection, "text")
    # 从字典中获取对应的标签页Frame对象
    current_tab = tab_frames[tabN]
    
    # 避免重复添加按钮,先清空当前标签页的内容
    for widget in current_tab.winfo_children():
        widget.destroy()
    
    # 根据标签名称添加对应按钮
    if tabN == 'Ed':
        tk.Button(current_tab, text=tabN).pack()
    elif tabN == 'Ted':
        tk.Button(current_tab, text=tabN).pack()

root = tk.Tk()
root.title("Tab")

uFrame = ttk.Notebook(root, style="TFrame")
uFrame.pack(pady=20)
uFrame.bind("<<NotebookTabChanged>>", loadtab)

pathOpt = ['Ed', 'Ted']
for name in pathOpt:
    tab = ttk.Frame(uFrame)
    uFrame.add(tab, text=name)
    # 将标签页对象存入字典,方便后续调用
    tab_frames[name] = tab

test = tk.Button(root, text='Deliniate tabs')
test.pack(pady=20)
root.mainloop()

关键改动

  1. 新增tab_frames字典,在循环创建标签页时,把每个ttk.Frame对象以标签名称为键存储起来,这样切换时能直接拿到对应的容器。
  2. 在loadtab函数中,通过标签名称从字典获取正确的Frame对象,而不是用字符串当作容器。
  3. 添加了清空标签页内容的逻辑,避免每次切换都重复添加按钮。

内容的提问来源于stack exchange,提问作者Chris W

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:25:24