Python 使用tkinter在单个窗口中将多个框架和小部件组合在一起

Python 使用tkinter在单个窗口中将多个框架和小部件组合在一起,python,user-interface,tkinter,Python,User Interface,Tkinter,我正在尝试构建一个基本上只有一个窗口的GUI。此窗口是不同框架的组合。我想做的是将这些框架(每个框架还包括多个小部件)以某种格式排列在一起: 第一帧(左上):从上到左为窗口大小的一半 第二个框架(左下):从底部到左侧为窗口大小的一半 第三帧(右上):距离窗口顶部的1/3大小和距离窗口右侧的一半大小 第四帧(右下):窗口上的剩余空间 下面,我为这个问题添加了一个简单的简约代码。为了保持简单,我使用了相同的FRAME类并创建了该类的4个实例以添加到主窗口中。我使用Tkinter的网格管理器来组织

我正在尝试构建一个基本上只有一个窗口的GUI。此窗口是不同框架的组合。我想做的是将这些框架(每个框架还包括多个小部件)以某种格式排列在一起:

  • 第一帧(左上):从上到左为窗口大小的一半
  • 第二个框架(左下):从底部到左侧为窗口大小的一半
  • 第三帧(右上):距离窗口顶部的1/3大小和距离窗口右侧的一半大小
  • 第四帧(右下):窗口上的剩余空间
下面,我为这个问题添加了一个简单的简约代码。为了保持简单,我使用了相同的FRAME类并创建了该类的4个实例以添加到主窗口中。我使用Tkinter的网格管理器来组织框架中的小部件,然后再次使用网格管理器将这些框架打包到主窗口中

import Tkinter as tk 

# Test frame class. The same frame is used to create 4 instances. 
class TestFrame(tk.Frame): 
    def __init__(self, master=None, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        super().__init__(master)

        # Test Entry fields
        test_label_1                = tk.Label(master, text="Test Label 1").grid(row=0, column=0)
        test_label_1_entry          = tk.Entry(master, bd=5).grid(row=0, column=1)
        test_label_2                = tk.Label(master, text="Test Label 2").grid(row=0, column=2)
        test_label_2_entry          = tk.Entry(master, bd=5).grid(row=0, column=3)

        # Test checkbox fields
        test_checkbox_1_label       = tk.Label(master, text="Test check button 1").grid(row=2, column=0)
        test_checkbox_1_entry       = tk.Checkbutton(master, bd=5).grid(row=2, column=1)
        test_checkbox_2_label       = tk.Label(master, text="Test check button 2").grid(row=2, column=2)
        test_checkbox_2_entry       = tk.Checkbutton(master, bd=5).grid(row=2, column=3)

        # Test dropdowns
        test_dropdown_label         = tk.Label(master, text="Test dropdown 1").grid(row=3, column=0)
        list_of_options             = ["first option", "second option", "third option", "forth option"]
        first_option                = tk.StringVar(master)
        first_option.set(list_of_options[0])
        test_dropdown_label         = tk.OptionMenu(master, first_option, *list_of_options).grid(row=3, column=1)
        test_dropdown_label         = tk.Label(master, text="Test dropdown 1").grid(row=3, column=0)
        list_of_options             = ["first option", "second option", "third option", "forth option"]
        first_option                = tk.StringVar(master)
        first_option.set(list_of_options[0])
        test_dropdown_label         = tk.OptionMenu(master, first_option, *list_of_options).grid(row=3, column=1)
        pass 

    pass

class TestMainApplication(tk.Frame):

    def __init__(self, master, *args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)
        super().__init__(master)

        title                       = "Test Application"
        self.grid()

        # Assign the weight to each row and column as 1. This is required to align the parameters in grid.
        for r in range(3):
            self.master.rowconfigure(r, weight=1)    
        for c in range(8):
            self.master.columnconfigure(c, weight=1)

        self.master.title(title)

        # Add two instances of the class TestFrame
        self.testFrame1            = TestFrame(master)
        self.testFrame2            = TestFrame(master)
        self.testFrame3            = TestFrame(master)
        self.testFrame4            = TestFrame(master)

        self.testFrame1.grid(row=0, column=0, rowspan=3, columnspan=3, sticky=tk.W+tk.E+tk.N+tk.S)
        self.testFrame2.grid(row=3, column=0, rowspan=3, columnspan=3, sticky=tk.W+tk.E+tk.N+tk.S)  
        self.testFrame3.grid(row=0, column=3, rowspan=2, columnspan=3, sticky=tk.W+tk.E+tk.N+tk.S)
        self.testFrame3.grid(row=2, column=3, rowspan=4, columnspan=3, sticky=tk.W+tk.E+tk.N+tk.S)

        pass 
    pass 


# Main application is created here. 
root                   = tk.Tk()
mainApplication        = TestMainApplication(root)
root.mainloop()
我希望在运行这段代码之后,一个窗口会按照上面讨论的格式分成4部分。然而,我看到的是所有的帧重叠在一起


环境:MacOS、tkinter 8.6、python 3.6.7

好的,这里有一些问题

  • 你的代码有点乱。请考虑使用PEP8标准。
  • 如果要对框架使用类内在性,为什么不对根窗口使用同样的方法呢。我已编辑了您的代码以从
    Tk()
    继承

  • 重叠的原因是因为在
    TestFrame
    类中,您告诉您的小部件它们属于
    master
    ,而不是
    self
    (即TestFrame类本身)。要更正此问题,只需将TestFrame中的所有
    master
    调用替换为
    self

  • 您可以同时使用
    tk.Frame.\uuuu init\uuuu(self)
    super()。当使用这种内在性时,实际上只需要使用
    super()。\uuu init\uuuu()

  • 请参见下面的示例代码:

    import tkinter as tk
    
    
    class TestFrame(tk.Frame):
        def __init__(self):
            super().__init__()
            list_of_options = ["first option", "second option", "third option", "forth option"]
            first_option = tk.StringVar(self)
            first_option.set(list_of_options[0])
    
            tk.Label(self, text="Test Label 1").grid(row=0, column=0)
            tk.Entry(self, bd=5).grid(row=0, column=1)
            tk.Label(self, text="Test Label 2").grid(row=0, column=2)
            tk.Entry(self, bd=5).grid(row=0, column=3)
            tk.Label(self, text="Test check button 1").grid(row=2, column=0)
            tk.Checkbutton(self, bd=5).grid(row=2, column=1)
            tk.Label(self, text="Test check button 2").grid(row=2, column=2)
            tk.Checkbutton(self, bd=5).grid(row=2, column=3)
            tk.Label(self, text="Test drop down 1").grid(row=3, column=0)
            tk.OptionMenu(self, first_option, *list_of_options).grid(row=3, column=1)
    
    
    class TestMainApplication(tk.Tk):
        def __init__(self):
            super().__init__()
            self.title("Test Application")
    
            for r in range(3):
                self.rowconfigure(r, weight=1)
            for c in range(8):
                self.columnconfigure(c, weight=1)
    
            self.testFrame1 = TestFrame()
            self.testFrame2 = TestFrame()
            self.testFrame3 = TestFrame()
            self.testFrame4 = TestFrame()
            self.testFrame1.grid(row=0, column=0, rowspan=3, columnspan=3, sticky='nsew')
            self.testFrame2.grid(row=3, column=0, rowspan=3, columnspan=3, sticky='nsew')
            self.testFrame3.grid(row=0, column=3, rowspan=2, columnspan=3, sticky='nsew')
            self.testFrame3.grid(row=2, column=3, rowspan=4, columnspan=3, sticky='nsew')
    
    
    TestMainApplication().mainloop()