Python 使用tkinter的框架布局中的框架

Python 使用tkinter的框架布局中的框架,python,tkinter,Python,Tkinter,我想创建tkinter网格布局5帧。在替换框架内容之前,它看起来就像我想要的那样 self.Frame1 = tk.Frame(self.parent, bg="grey") 与 当我最大化窗口时,我看到LeftUpper窗口框架中的所有内容都乱七八糟,布局不正确。一幅画抵得上千言万语,所以我有这个 我想要这个 概述 你的问题没有速效药。您在代码中做了一些事情,这些事情对您不利,这使得调试代码非常困难。重写是最好的解决方案 以下是我发现的使问题变得比需要的更困难的事情,可以通过重写来解决

我想创建tkinter网格布局5帧。在替换框架内容之前,它看起来就像我想要的那样

self.Frame1 = tk.Frame(self.parent, bg="grey")

当我最大化窗口时,我看到LeftUpper窗口框架中的所有内容都乱七八糟,布局不正确。一幅画抵得上千言万语,所以我有这个

我想要这个

概述 你的问题没有速效药。您在代码中做了一些事情,这些事情对您不利,这使得调试代码非常困难。重写是最好的解决方案

以下是我发现的使问题变得比需要的更困难的事情,可以通过重写来解决

首先,不要让一个小部件负责将自己放在其父部件中。在您的例子中,您将更进一步,让一个小部件将它的父对象放到它的祖辈对象中。这完全是错误的做法。一个包含窗口应该负责它的子窗口的布局,仅此而已

其次,将尽可能多的布局代码放在一起。我所说的“全部”是指“给定容器的全部”。因此,例如,与此相反:

x=Label(...)
x.grid(...)
y =Label(...)
y.grid(...)
。。。这样做:

x = Label(...)
y = Label(...)
x.grid(...)
y.grid(...)
这使得在代码中可视化布局更加容易

第三,不要试图一次解决多个布局问题。一次解决一个问题。既然你发布了整个程序,我想你对整个程序有问题,而不仅仅是左上角的小部件。当我运行您的代码时,我观察到调整大小的行为,这在我看来似乎是不对的,这强化了我的信念

第四,如果您创建了一个像MainWindow这样的类来包含其他小部件,那么所有这些其他小部件都将是窗口的子部件,而不是父部件的子部件

第五,作为一般的经验法则,您只希望带有容器的单行和单列具有非零权重。这只是一个指导原则,因为有时您需要扩展或收缩多个小部件。在滚动条和状态标签的情况下,通常不希望给它们额外的空间。代码中的一部分问题是,您为所有内容赋予了权重,因此为每个小部件分配了额外的空间

解决方案 解决方案是一次只处理一个部分。让它工作起来,然后进入下一节。在你的例子中,我看到工作分为四个阶段。首先,创建并布置主窗口。接下来,添加作为主窗口直接子窗口的小部件。然后,为左上角窗口创建容器。最后,将小部件添加到左上角窗口。在每个阶段之后,确保运行代码并验证一切正常

主窗口 第一步是从主窗口开始。调整主窗口的大小时,使其外观正确,行为正常。当我运行代码时,当窗口变小时,底部和右侧窗口将消失,而当窗口变大时,底部框架将增长。我猜这不是正确的行为。无论如何,在添加更多小部件之前,先从您认为正确的行为开始,并使其正常工作

从下面的代码开始。确认在调整窗口大小时,所有内容都按预期方式展开和收缩。注意,我做了几个简单的更改。需要注意的主要问题是,创建主窗口的函数负责使该窗口可见。我使用
pack
,因为它是根窗口中唯一的小部件,这意味着我可以在一行中完成所有操作,而不必担心网格中的行和列的权重

import sys
import os

import Tkinter as tk
import ttk as ttk

class MainWindow(tk.Frame):
    def __init__(self, master=None):
        self.parent = master
        tk.Frame.__init__(self, self.parent, bg='bisque', borderwidth=1, relief="sunken")
        self.__create_layout()

    def __create_layout(self):
        pass

#
#   MAIN
#
def main():
    root = tk.Tk()

    root.title("Frames")
    root.geometry("550x300+525+300")

    root.configure(background="#808080")
    root.option_add("*font", ("Courier New", 9, "normal"))

    window = MainWindow(master=root)
    window.pack(side="top", fill="both", expand=True)
    root.mainloop()

if __name__ == '__main__':
    main()
主窗口中的小部件 一旦
main窗口
shell运行正常,就可以添加更多小部件了。看起来您有五个框架,尽管其中一个是自定义类。现在我们将使用一个常规框架来保持简单。你给每个人一个颜色是很好的,这是一个很好的方式来可视化布局,因为你建立了窗口

修改
\u创建\u布局
,如下所示。注意两个重要的变化:每个小部件都是
self
的子部件,而不是
self.parent
,我将所有布局代码组合在一起

我对调整大小的行为很反感,但我不知道你到底想要什么。对我来说,让绿色、红色和粉色的框架按照它们的方式调整大小似乎很奇怪,尽管这可能是你想要的。不管怎样,现在是正确的时候了

def __create_layout(self):
    self.Frame1 = tk.Frame(self, bg="grey")
    self.Frame2 = tk.Frame(self, bg="blue")
    self.Frame3 = tk.Frame(self, bg="green")
    self.Frame4 = tk.Frame(self, bg="brown")
    self.Frame5 = tk.Frame(self, bg="pink")

    self.Frame1.grid(row=0, column=0, rowspan=4, columnspan=8, sticky=(tk.N, tk.S, tk.W, tk.E))
    self.Frame2.grid(row=0, column=8, rowspan=4, columnspan=2, sticky=(tk.N, tk.S, tk.W, tk.E))
    self.Frame3.grid(row=4, column=0, rowspan=2, columnspan=5, sticky=(tk.N, tk.S, tk.W, tk.E))
    self.Frame4.grid(row=4, column=5, rowspan=2, columnspan=5, sticky=(tk.N, tk.S, tk.W, tk.E))
    self.Frame5.grid(row=5, column=0, rowspan=1, columnspan=10, sticky=(tk.N, tk.S, tk.W, tk.E))

    for r in range(6):
        self.rowconfigure(r, weight=1)
    for c in range(10):
        self.columnconfigure(c, weight=1)
LeftUpperWindow小部件 接下来,让我们定义
LeftUpperWindow
类,并确保没有破坏任何内容。为类添加一个存根,给窗口一个独特的颜色,并确保窗口在显示和调整大小时仍然看起来正常

class LeftUpperWindow(tk.Frame):
    def __init__(self, master=None):
        self.parent = master
        tk.Frame.__init__(self, self.parent, bg='bisque', borderwidth=1, relief="sunken")
        self.__create_layout()

    def __create_layout(self):
        pass
请记住修改
main窗口。\uuuu create\u layout
以创建此类而非框架的实例:

self.frame1 = LeftUpperWindow(self)
LeftUpper窗口中的小部件 最后,是在
LeftUpperWindow
中添加小部件的时候了。就像我们在
MainWindow
中所做的那样,小部件都是
self
的子部件,小部件创建和小部件布局是在单独的组中完成的。另外,通常最好只为单行和单列指定非零权重。这通常是文本或画布小部件所在的行和列

当然,你可以做你想做的事。请注意,由于您在原始代码中为每一行和每一列赋予了权重,这就增加了小部件之间的所有空间

另外,因为您要给GUI一个显式的大小(通过
root.geometry(…)
),所以您希望给文本小部件一个小的大小。否则,默认宽度和高度将推出其他小部件,因为tkinter会尝试为每个小部件指定其默认大小。由于您要限制整个窗口大小,因此希望文本小部件尽可能小,然后让
网格
展开它以填充整个窗口
class LeftUpperWindow(tk.Frame):
    def __init__(self, master=None):
        self.parent = master
        tk.Frame.__init__(self, self.parent, bg='bisque', borderwidth=1, relief="sunken")
        self.__create_layout()

    def __create_layout(self):
        pass
self.frame1 = LeftUpperWindow(self)
def __create_layout(self):
    self.editArea = tk.Text(self, wrap=tk.NONE, undo=True,
                            width=1, height=1,
                            relief=tk.SUNKEN, borderwidth=5, 
                            highlightthickness=0, insertbackground="white")
    self.editArea.config(font=('courier', 10, 'normal'))
    self.editArea.configure(bg="black", fg="white")

    self.scrollbarY = tk.Scrollbar(self, orient=tk.VERTICAL)
    self.scrollbarX = tk.Scrollbar(self, orient=tk.HORIZONTAL)
    self.status = tk.Label(self, text="Status label", bd=1, relief=tk.SUNKEN, 
                           anchor=tk.W,  bg='lightgray')

    self.editArea.grid(row=0, column=0, sticky=(tk.N, tk.S, tk.W, tk.E))
    self.scrollbarY.grid(row=0, column=1, sticky=(tk.N, tk.S), rowspan=2)
    self.scrollbarX.grid(row=1, column=0, sticky=(tk.W, tk.E))
    self.status.grid(row=2, column=0, sticky=(tk.N, tk.S, tk.W, tk.E), columnspan=2)

    self.rowconfigure(0, weight=1)
    self.columnconfigure(0, weight=1)