问题描述
@H_404_0@我从原始代码中定义的笔记本开始,它有 4 个选项卡,每个选项卡都有一个关联的 Frame(Tab1 有一个名为 page1 的 Frame,Tab2 有 page2,依此类推)。对于前两个选项卡,我有在每一帧中放置一个画布并在该画布上绘制图形的函数。所以我可以在运行时在代码中将项目放置在这些预定义的标签页上。
@H_404_0@我的目标是能够在笔记本中放置额外的、计划外的标签,使用功能,然后将信息放置在与新标签关联的页面上。
@H_404_0@我有一个函数 Command3() - 见下文 - 我在其中即时创建选项卡。
@H_404_0@'''
。所以命令 3 似乎已经工作并创建了适当的 Frame 对象。
@H_404_0@我的目的是计算“页面”名称,以便我可以重复执行此操作并使用如下代码:
@H_404_0@'''
def command3():
#command invoked by button 3 - add a tab to the notebook
tab_caption = simpledialog.askstring('Tab Text','Enter Text for Tab')
ntn = len(nb.tabs()) + 1
if tab_caption == '':
tab_caption = 'Tab ' + str(ntn)
var_name = 'page' + str(ntn)
command_string = var_name + ' = tk.Frame(nb)'
exec(command_string)
command_string = 'nb.add('+var_name+',text = tab_caption)'
exec(command_string)
@H_404_0@'''
@H_404_0@上面的代码工作得很好。当我执行此代码(通过单击 Button3)时,我会得到一个新选项卡,其中包含我在对话框中提供的文本,该对话框具有一个名为“第 5 页”的内部框架。我可以点击选项卡并选择它(它什么都不显示,因为我没有在那里放置任何东西),我什至可以在代码中更改选项卡的名称。
@H_404_0@我的问题是,当我尝试在“第 5 页”上放置任何内容时,什么也没有出现。下面的函数 Command4 旨在将标签放置在页面上的任何位置。
@H_404_0@'''
def command4():
#command invoked by button 4 - add label
last_tab = len(nb.tabs())
last_tab_index = last_tab-1
page_name = 'page' + str(last_tab)
nb.tab(last_tab_index,text = 'Repeat Graph')
print(last_tab)
print(last_tab_index)
print(page_name)
labelTest = tk.Label(page5,text = 'Something')
labelTest.pack()
@H_404_0@'''
当这段代码执行时,选项卡名称发生变化,打印语句全部起作用,最后两行似乎没有错误地执行,但在 Tab5 的框架中没有任何显示(框架是 page5)。
@H_404_0@Python 似乎知道第 5 页存在(当我终止程序并在 Idle 中键入 >>> page 5 时,我得到 def command4():
#command invoked by button 4 - add label
last_tab = len(nb.tabs())
last_tab_index = last_tab-1
page_name = 'page' + str(last_tab)
nb.tab(last_tab_index,text = 'Repeat Graph')
print(last_tab)
print(last_tab_index)
print(page_name)
command_string = "labelTest = tk.Label(" + page_name + ",text = 'Something')"
exec(command_string)
labelTest.pack()
@H_404_0@'''
@H_404_0@当我执行此代码时,exec(command_string) 不会产生任何错误,但是,当软件执行 labelTest.pack() 命令时,我收到一个错误,指出名称 labelTest 未定义。
@H_404_0@这是范围问题吗?有没有另一种方法来处理这个问题?有没有办法使用内部的“.!frame2.!notebook.!frame5”符号来完成同样的事情?
解决方法
你不需要使用exec
,你可以简单地使用一个局部变量。在这件事上使用 exec
几乎从来都不是正确的做法。
例如:
def command3():
tab_caption = simpledialog.askstring('Tab Text','Enter Text for Tab')
ntn = len(nb.tabs()) + 1
if tab_caption == '':
tab_caption = 'Tab ' + str(ntn)
tab_frame = tk.Frame(nb)
nb.add(tab_frame,text=tab_caption)
# inside the function you can add other widgets
label = tk.Label(tab_frame,text="Hello,world")
label.pack()
如果您想在函数外的框架中添加项目,请让函数返回框架。
def command3():
...
return tab_frame
然后,在调用 command3 的代码中,您可以通过返回的框架添加小部件:
new_tab_frame = command3()
label = tk.Label(new_tab_frame,world")
您几乎可以在任何地方使用 tabs
方法返回的值。但是,该方法返回内部小部件的名称,必须将其转换为实际小部件才能使用:
last_frame = nb.nametowidget(nb.tabs()[-1])
label = tk.Label(last_frame,...)
如果您更喜欢象征性地引用选项卡(即:按名称而不是按索引),您可以将框架存储在字典中:
frames = {}
def command3():
#command invoked by button 3 - add a tab to the notebook
tab_caption = simpledialog.askstring('Tab Text','Enter Text for Tab')
ntn = len(nb.tabs()) + 1
if tab_caption == '':
tab_caption = 'Tab ' + str(ntn)
tab_frame = tk.Frame(nb)
frames[tab_caption] = tab_frame
nb.add(tab_frame,text=tab_caption)
...
# add a label to the tab named "Tab 1":
tab_frame = frames["Tab 1"]
label = tk.Label(tab_frame,...)