2015-10-03 94 views
0

我正在构建一个GUI应用程序来监视/控制远程嵌入式客户端设备。每个客户端的状态机都维护在一个主字典中,并将在GUI中作为Notebook小部件中的一个选项卡(Frame)的实例来表示。每当新客户端注册并隐藏或忘记客户端链接超时时的选项卡时,我想实例化一个选项卡(在我的应用程序中定义为类)。我将重新实例化客户端是否重新注册。基于Dictionary Record值动态添加,隐藏或忘记Tkinter帧?

我是Python,Tkinter和OO的新手,一直在努力应对程序结构。我需要持续循环查看字典记录以刷新GUI,但我已经得出结论,我无法在root.mainloop()结构中进行迭代。因此,状态机字典记录或元素中的“外部”更改需要从外部刷新相应的GUI Notebook标签实例,包括创建和删除标签类的实例。

我相信有一个标准的做法,但我没有充分发展,在我的学习中弄清楚这一点。一些快速的建议,让我在正确的方向推动我将不胜感激。

+0

你是对的,你不应该在事件处理程序中连续(或非常长)循环。 tkinter的替代品是使用.after函数。这里有几个关于SO的例子,包括我的一些例子。 –

+0

Found,after,包括你的一个例子。这似乎是我需要在我的GUI对象中刷新的解决方案......只需要将我的范例转换为在对象内部进行字典管理,而不是像我正在尝试的那样在外部进行。谢谢! – w9lp

回答

0

我需要解决的三个要素,让我的解决办法工作。

1)使用root.after功能,使外部异步事件(如非Tkinter的GUI事件)使用更新的方法来控制GUI元素......谢谢你,特里Jan Reedy!

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

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

下面的代码片段。

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) 
+0

很高兴看到有人用提示来解决他的问题。自顶向下控制的传统命令式编程的角度来看,事件循环编程似乎可以更新。 Twisted包的名称就是为了反映这一点。如果你用gui做了其他事情,并发现gui_update锁定了gui太久了,你可以分成'update_new','update_old'和'update_all',并且每个都以循环方式设置下一个,延迟时间总计大约为1000 - 执行时间。 IE,'update_new'可以'root.after(0,update_old)'结尾。 –

+0

伟大的见解......感谢你。我最后一次编程的直接经验是MC6800 Assembly和C ...嵌入并自上而下。刚刚开始加速OO,套接字和GUI。 ;-) 感谢你的帮助。 – w9lp