【问题标题】:Adding tabs to a Notebook at runtiime with a function - I can create the tab and its inner frame, but cannot add components to the frame在运行时使用函数将选项卡添加到笔记本 - 我可以创建选项卡及其内部框架,但不能将组件添加到框架
【发布时间】:2021-03-18 18:47:04
【问题描述】:

我从原始代码中定义为具有 4 个选项卡的笔记本开始,每个选项卡都有一个关联的框架(Tab1 有一个名为 page1 的框架,Tab2 有一个 page2,依此类推)。对于前两个选项卡,我有在每一帧中放置一个画布并在该画布上绘制图形的函数。所以我可以在代码中在运行时将项目放置在这些预定义的标签页上。

我的目标是能够使用功能将额外的、计划外的选项卡放置到笔记本中,然后将信息放置在与新选项卡关联的页面上。

我有一个函数 Command3() - 见下文 - 我在其中动态创建选项卡。

'''

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)

'''

上面的代码工作得很好。当我执行此代码时(通过单击 Button3),我得到一个新选项卡,其中包含我在对话框中提供的文本,该对话框具有一个名为“page 5”的内部框架。我可以点击选项卡并选择它(它什么也不显示,因为我没有放任何东西),我什至可以在代码中更改选项卡的名称。

我的问题是,当我尝试在“第 5 页”上放置任何内容时,什么都没有出现。下面的函数 Command4 旨在将标签放置在页面的任何位置。

'''

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

''' 执行此代码时,选项卡名称更改,打印语句全部正常工作,最后两行似乎执行没有错误,但 Tab5 的框架中没有出现任何内容(框架为 page5)。

Python 似乎知道第 5 页存在(当我终止程序并在 Idle 中键入 >>> 第 5 页时,我得到 。所以命令 3 似乎已经工作并创建了适当的 Frame 对象。

我的意图是计算“页面”名称,以便我可以重复执行此操作并使用如下代码:

'''

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

'''

当我执行此代码时,exec(command_string) 不会产生任何错误,但是,当软件执行 labelTest.pack() 命令时,我会收到一个错误,即名称 labelTest 未定义。

这是范围问题吗?有没有另一种方法来处理这个问题?有没有办法使用内部的“.!frame2.!notebook.!frame5”符号来完成同样的事情?

【问题讨论】:

    标签: python-3.x tkinter ttk


    【解决方案1】:

    你不需要使用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, text="Hello, 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, ...)
    

    【讨论】:

    • 非常感谢...工作就像一个魅力!感谢帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多