tkinter - 字典中的重复条目和意外的pack()行为

时间:2017-12-12 22:56:42

标签: python dictionary tkinter frame

我正在编写一个tkinter程序,该程序将具有多种模式,并希望更改窗口各个部分的帧以响应模式更改。

以下代码旨在创建一个可以在包含的帧之间切换的抽象SwitcherClass。 SwitchedFrame派生自SwitcherClass,并且有一个class属性,列出了应该切换的帧(在本例中为Myclass和Myotherclass)。

它有两个意想不到的行为:

  1. SwitcherClass中的词典self.children应该有两个条目,但最终会有四个条目。 SubClass对象最终在字典中作为键和值,因此每次运行循环都会创建两个字典条目!

  2. SwitcherClass中的pack()和pack_forget()调用什么都不做。实际上,如果SwitcherClass的子节点从未打包过,它们仍会显示在主窗口中。为什么呢?

  3. 我非常感谢这些谜题中的一个或两个的答案。

    import tkinter as tk
    
    class Myclass(tk.Frame):
        def __init__(self,parent):
            super().__init__(parent)
            tk.Button(text='Myclass',command=parent.switch).pack()
    
    class Myotherclass(tk.Frame):
        def __init__(self,parent):
            super().__init__(parent)
            tk.Button(text='Myotherclass',command=parent.switch).pack()
    
    class SwitcherClass(tk.Frame):
        def __init__(self,parent):
            super().__init__(parent)
            self.children = {}
            for label,Subclass in self.contains:
                self.children[label] = Subclass(self)
            print(self.children)
            self.frame = 'first'
            self.children[self.frame].pack()        
    
        def switch(self):
            old_frame = self.frame
            if self.frame == 'second':
                self.frame = 'first'
            else:
                self.frame = 'second'
            self.children[old_frame].pack_forget()
            self.children[self.frame].pack()
    
    class SwitchedFrame(SwitcherClass):
        contains = (('first',Myclass),('second',Myotherclass))
    
    
    root = tk.Tk()
    tk.Label(root,text='root frame').pack()
    SwitchedFrame(root).pack()
    root.mainloop()
    

1 个答案:

答案 0 :(得分:1)

首先: tkinter中的每个小部件都使用self.children来保留自己的孩子,因此请为您使用不同的名称 - 即。 self.my_children。现在,您会看到tkinter自动添加自己的小部件和小部件。

第二个:没有父级的窗口小部件已分配给root,因此您的按钮也会分配给root,您可以在主窗口中看到它们,而不是在子框架中看到它们(但他们改变没有按钮的框架没有尺寸)。

您必须使用Button(self, ...)指定按钮才能更正框架。

import tkinter as tk

class Myclass(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        tk.Button(self, text='Myclass',command=parent.switch).pack()

class Myotherclass(tk.Frame):
    def __init__(self,parent):
        super().__init__(parent)
        tk.Button(self, text='Myotherclass',command=parent.switch).pack()

class SwitcherClass(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.my_children = {}
        for label,Subclass in self.contains:
            self.my_children[label] = Subclass(self)
        for x in self.my_children:
            print('child:', x)
        self.frame = 'first'
        self.my_children[self.frame].pack()        

    def switch(self):
        old_frame = self.frame
        if self.frame == 'second':
            self.frame = 'first'
        else:
            self.frame = 'second'
        self.my_children[old_frame].pack_forget()
        self.my_children[self.frame].pack()

class SwitchedFrame(SwitcherClass):
    contains = (('first',Myclass), ('second',Myotherclass))


root = tk.Tk()
tk.Label(root,text='root frame').pack()
SwitchedFrame(root).pack()
root.mainloop()