基于字典记录值动态添加、隐藏或忘记 Tkinter 框架?

Dynamically add, hide or forget Tkinter Frames based on Dictionary Record values?

我正在为 monitor/control 远程嵌入式客户端设备构建一个 GUI 应用程序。每个客户端的状态机都保存在主字典中,并在 GUI 中表示为笔记本小部件中选项卡(框架)的实例。我想在新客户端注册时实例化一个选项卡(在我的应用程序中定义为 class),并在客户端 link 超时时隐藏或忘记该选项卡。我将重新实例化 if/when 客户端重新注册。

我是 Python、Tkinter 和 OO 的新手,我正在为程序结构而苦苦挣扎。我需要不断循环遍历字典记录以刷新 GUI,但我得出的结论是我无法在 root.mainloop() 结构中进行迭代。所以"external"状态机字典记录或元素的变化需要在外部刷新相应的GUI Notebook选项卡实例,包括创建和删除我的选项卡实例class。

我相信有一个标准的做法,但我在学习方面还没有取得足够的进步来弄清楚这一点。一些快速的建议可以帮助我朝着正确的方向前进,我们将不胜感激。

我需要解决三个要素才能让我的解决方案发挥作用:

1) 使用 root.after 函数启用外部异步事件(例如非 tkinter GUI 事件)以使用更新方法控制 GUI 元素...谢谢 Terry Jan Reedy!

2) 在 GUI 实例化本身内执行整体字典更新作为一种方法,而不是尝试使用单独的函数来处理我的字典管理。也许这对大多数人来说是显而易见的,但对我来说这是一个范式转变。

3) 对于所有字典元素,GUI 需要是我的 class 的单个实例,而不是每个元素的单独实例。

下面的代码片段。

def remote_window_mgr():
    remote_window = client_gui()


class client_gui(object):

    def __init__(self):

        self.root = Tk()
        self.root.title('Client Manager')

        # Create main Frame in Window
        main_frame = ttk.Frame(self.root, borderwidth = 5, relief = 'ridge')
        main_frame.grid(column = 0, row = 0, sticky = (N, W, E, S))
        main_frame.columnconfigure(0, weight = 1)
        main_frame.rowconfigure(0, weight = 1)

        # Create Notebook widget to host Client Tabs
        self.tab_frame = ttk.Notebook(main_frame)
        self.tab_frame.grid(column = 1, row = 1)

        self.root.after(1000, func=self.gui_update)
        self.root.mainloop()


    def gui_update(self):

        for client_id in list(Client_Records.keys()):
            # Check for new Client
            if client_id not in list(Client_Tabs.keys()):
                client_data = Client_Records[client_id]
                # Create Client Tab
                self.add_tab(client_id)

        for client_id in list(Client_Tabs.keys()):
            # Check if Client Record has been purged...
            if client_id not in list(Client_Records.keys()):
                # Client Record no longer exists, delete Client Tab
                self.remove_tab(client_id)
                del Client_Tabs[client_id]

        for client_id in list(Client_Tabs.keys()):
            # Refresh client tabs for all active clients
            self.update_tab(client_id)

        self.root.after(1000, func=self.gui_update)