首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Tkinter笔记本<<NotebookTabChanged>>问题

Tkinter笔记本<<NotebookTabChanged>>问题
EN

Stack Overflow用户
提问于 2022-04-17 11:18:42
回答 2查看 205关注 0票数 0

我正在构建一个基于Tkinter“笔记本”对象的UI,该对象有几个选项卡。每当用户单击选项卡时,我都希望根据基础对象的当前状态更新框架上的信息,然后再将其显示给用户。

这似乎不起作用:

下面的演示构建了一个三页的笔记本。例程load_page绑定到NotebookTabChanged事件,每次单击选项卡时都应该调用该事件。此例程应打开一个消息窗口,标识触发该选项卡的选项卡,并更新页面上的信息(使用当前时间):

代码语言:javascript
运行
复制
import tkinter as tk
import tkinter.messagebox as msg
from tkinter import ttk
import time

class DemoPage(tk.Frame):  # A notebook page
    def __init__(self, container, name: str = ""):
        # call the superclass init to build the page
        tk.Frame.__init__(self, container, highlightbackground="blue", highlightthickness=1)
        self._name = name  # The name of the page (appears on the page tab)
        container.add(self, text=name)  # add the notebook tab & associate w. page
        # event binding
        container.bind("<<NotebookTabChanged>>", func=self.load_page)  # load current table 
        # insert texts
        self.const_label = tk.Label(self, text="This is " + self._name)
        self.const_label.pack(side='top', fill='x')
        self.var_label = tk.Label(self, text="Updated " + time.ctime())
        self.var_label.pack(side='top', fill='x')

    def load_page(self, event):
        self.var_label["text"] = "Updated " + time.ctime()
        msg.showinfo(self._name, "Tab clicked")

if __name__ == "__main__":
    tk_win = tk.Tk()  # establish the root tkinter window
    tk_win.title("Master Sequence")
    tk_win.geometry("600x400")
    # initiate UI
    nb = ttk.Notebook(tk_win)  # establish notebook 
    nb.pack(expand=True, fill='both')  # widget geometry: Notebook will fill the root window
    page1 = DemoPage(nb,"Page 1")  # initiate tab object in the notebook
    page2 = DemoPage(nb,"Page 2")  # initiate tab object in the notebook
    page3 = DemoPage(nb,"Page 3")  # initiate tab object in the notebook
    # wait for user input
    tk_win.mainloop()

请注意,当应用程序第一次运行时(不单击其选项卡),该事件将自动触发到第3页。此后,每次单击任何选项卡时,都会为选项卡3触发该事件的,而帧中的信息仅在第3页的中被更新。

我做错了什么?

EN

回答 2

Stack Overflow用户

发布于 2022-04-17 12:05:15

NotebookTabChanged不仅仅是click事件--它也可以使用代码生成--当您创建新的选项卡时,它也会生成这个事件。您应该首先创建所有选项卡,然后创建绑定事件。它可能需要使用tk_win.update()

但是这个事件的工作方式与您预期的不同--它被分配给Notebook,而不是选项卡--所以您用新的bind替换了previus bind,最后它运行了最后一个被访问的函数,该函数更改了最后一个选项卡中的时间。

您应该使用一个函数来检查哪个选项卡是活动的,并在此选项卡中更改时间。但是,如果您在列表中保留选项卡,则会更简单--因此您可以获取活动选项卡的索引,并使用它访问列表上的选项卡。

代码语言:javascript
运行
复制
def on_tab_change(event):
    index = nb.index(nb.select())
    print('index:', index)
    
    pages[index].load_page()

pages = [
    DemoPage(nb, "Page 1"),
    DemoPage(nb, "Page 2"),
    DemoPage(nb, "Page 3"),
]

nb.bind("<<NotebookTabChanged>>", on_tab_change)

完整的工作代码。

代码语言:javascript
运行
复制
import tkinter as tk
import tkinter.messagebox as msg
from tkinter import ttk
import time

class DemoPage(tk.Frame):  # A notebook page
    def __init__(self, container, name: str = ""):
        # call the superclass init to build the page
        tk.Frame.__init__(self, container, highlightbackground="blue", highlightthickness=1)
        self._name = name  # The name of the page (appears on the page tab)
        container.add(self, text=name)  # add the notebook tab & associate w. page
    
    
        # insert texts
        self.const_label = tk.Label(self, text="This is " + self._name)
        self.const_label.pack(side='top', fill='x')
        
        self.var_label = tk.Label(self, text="Updated " + time.ctime())
        self.var_label.pack(side='top', fill='x')

    def load_page(self):
        self.var_label["text"] = "Updated " + time.ctime()
        msg.showinfo(self._name, "Tab clicked")

def on_tab_change(event):
    index = nb.index(nb.select())
    print('index:', index)
    
    pages[index].load_page()

if __name__ == "__main__":
    tk_win = tk.Tk()  # establish the root tkinter window
    tk_win.title("Master Sequence")
    tk_win.geometry("600x400")

    # initiate UI
    nb = ttk.Notebook(tk_win)  # establish notebook 
    nb.pack(expand=True, fill='both')  # widget geometry: Notebook will fill the root window
    
    pages = [
        DemoPage(nb, "Page 1"),
        DemoPage(nb, "Page 2"),
        DemoPage(nb, "Page 3"),
    ]
    
    tk_win.update() # update all tabs before assigning `event`

    # assign only one function
    nb.bind("<<NotebookTabChanged>>", on_tab_change)
    
    tk_win.mainloop()
票数 1
EN

Stack Overflow用户

发布于 2022-04-18 12:22:26

谢谢弗拉斯。

事实上,NotebookTabChanged似乎并不像我所需要的那样运作。要提供同样的功能,一个简单得多的解决方案是更改行:

代码语言:javascript
运行
复制
container.bind("<<NotebookTabChanged>>", func=self.load_page)

至:

代码语言:javascript
运行
复制
self.bind("<Expose>", func=self.load_page)

当用户单击相关选项卡时,将公开"DemoPage“框架并触发事件。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71901422

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档