Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Tkinter:网格还是网格内的包?_Python_Layout_Tkinter - Fatal编程技术网

Python Tkinter:网格还是网格内的包?

Python Tkinter:网格还是网格内的包?,python,layout,tkinter,Python,Layout,Tkinter,我正在为软件构建GUI,并希望实现以下目标: ###################################### # | some title # # menu upper |----------------------# # | # # | CANVAS # # menu lower |

我正在为软件构建GUI,并希望实现以下目标:

######################################
#             |      some title      #
# menu upper  |----------------------#
#             |                      #
#             |         CANVAS       #
# menu lower  |                      #
#             |                      #
#------------------------------------#
#              statusbar             #
######################################
上菜单有一些高级功能,下菜单根据用户输入的不同而变化。Statusbar经常更改其内容


不幸的是,特金特拒绝工作

使用网格布局管理器我无法创建稳定的设计,无法将标签和按钮等内容添加到左侧的菜单中:

self.root = tk.Tk()
self.root.resizable(width=0, height=0)
self.root.title("some application")

# menu left
self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
self.menu_left.grid(row=0, column=0, rowspan=2, sticky="ns")

self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
self.menu_left_upper.grid(row=0, column=0)

# this label breaks the design   
#self.test = tk.Label(self.menu_left_upper, text="test")
#self.test.pack()

self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")
self.menu_left_lower.grid(row=1, column=0)

# right area
self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")
self.some_title_frame.grid(row=0, column=1, sticky="we")

self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
self.some_title.pack()

self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
self.canvas_area.grid(row=1, column=1)

self.root.mainloop()
此设计在没有左侧菜单内容的情况下工作。每当我在
self.menu\u left\u upper
self.menu\u left\u lower
中添加一些内容时,比如
测试标签,我的设计就被破坏了:菜单框消失了。
此外,即使使用columnspan,我也必须删除状态栏,因为当添加状态栏时,左侧的菜单再次消失


使用包布局管理器
我得到了以下结果:

######################################
#             |      some title      #
#             |----------------------#
# menu upper  |                      #
#             |         CANVAS       #
#             |                      #
# menu lower  |                      #
#             |----------------------#
#             |       statusbar      #
######################################
由于我希望左侧的菜单框使用完整的y空间,我使用
pack(side=“left”,expand=True,fill=“both”)
使其增长,但此设置始终拒绝状态栏的全宽

此外,纯包管理器代码看起来“丑陋”。我认为使用网格管理器的设计更“清晰”。因此,我认为网格布局或网格布局内的包布局会很好



有人能帮忙吗?我被困在GUI地狱中:/

self.root.mainloop()之前添加以下代码即可实现所需功能

self.some_status = tk.Label(self.root, text="status bar", bg="#dfdfdf")
self.some_status.grid(row=3, column=0, columnspan=2, sticky="we")

通过加入以下内容:

menu_left_upper.grid_propagate(False) 
菜单左上方
框架和
菜单左上方.mainloop()之间

其作用如下:

默认情况下,容器小部件会展开或折叠到刚好可以容纳其内容的大小。因此,当您调用pack时,它会导致帧收缩。此功能称为几何体传播

对于绝大多数应用程序,这是您想要的行为。对于那些很少需要显式设置容器大小的情况,可以关闭此功能。要关闭它,请在容器上调用
pack\u propagate
grid\u propagate
(取决于您是在该容器上使用grid还是pack),并将其值设置为
False

要获取状态栏,只需实现另一个框架和网格方法:

status_bar_frame = Frame(root, bg="#dfdfdf")
status_bar_frame.grid(row=3, column=0, columnspan=2, sticky="we")

status_bar = Label(status_bar_frame, text="status bar", bg="#dfdfdf")
status_bar.pack()
那你的计划就行了。 希望有帮助:)

还有,为什么所有的
self
属性

编辑: 要工作,你需要做:

menu_left_upper = Frame(menu_left, width=225, height=225, bg="red")
menu_left_upper.grid_propagate(False)
menu_left_upper.grid(row=0, column=0)

# this label breaks the design   
test = Label(menu_left_upper, text="test", bg='red')
test.grid()

布局的关键在于有条不紊,并使用正确的工具 为了这份工作。这也意味着有时候你需要有创造力。 这意味着在一个网格中布局时使用
网格
网格
,在从上到下或 从左到右

另一个关键是将布局代码分组在一起。很多很多 当布局都在一个块中时,更易于可视化和修改布局 代码的定义

在您的情况下,您似乎有三个或四个不同的区域,这取决于 看你怎么算。如果要使用
网格
,最容易 将“菜单上部”和“菜单下部”组合成一个框架,并处理该框架 整个框架作为一个表格单元。看起来你已经这么做了, 这很好

那么,让我们从这些主要领域开始:

self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
self.some_title_frame.grid(row=0, column=1, sticky="ew")
self.canvas_area.grid(row=1, column=1, sticky="nsew") 
# you don't have a status bar in the example code, but if you
# did, this is where you would put it
# self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")
无论何时使用
网格
,都需要至少给出一行和一行 列一个正权重,以便tkinter知道在哪里使用任何 未分配的空间。通常有一个小部件是“主” 小装置。在这种情况下,它是画布。你想确保 画布的行和列的权重为1(一):

注意:使用
pack
而不是
grid
将为您节省两行代码,因为
pack
不需要您像
grid
那样设置权重

接下来,我们需要解决菜单区域的问题。默认情况下, 框架收缩以适应其内容,这就是添加标签的原因 破坏了你的布局。你没有告诉tkinter如何处理额外的空间,所以框架缩小到合适的位置,多余的空间就没有用了

因为您希望“菜单上方”和“菜单下方” 每个共享50%的面积,
pack
是最简单的解决方案。你可以 使用
网格
,但它需要更多的代码行来添加行和列的权重

self.menu_left_upper.pack(side="top", fill="both", expand=True)
self.menu_left_lower.pack(side="top", fill="both", expand=True)
这是一个运行版本,带有状态栏。请注意,它的行为与调整窗口大小时的行为完全相同:

import Tkinter as tk

class Example():
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("some application")

        # menu left
        self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
        self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
        self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")

        self.test = tk.Label(self.menu_left_upper, text="test")
        self.test.pack()

        self.menu_left_upper.pack(side="top", fill="both", expand=True)
        self.menu_left_lower.pack(side="top", fill="both", expand=True)

        # right area
        self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")

        self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
        self.some_title.pack()

        self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
        self.canvas_area.grid(row=1, column=1)

        # status bar
        self.status_frame = tk.Frame(self.root)
        self.status = tk.Label(self.status_frame, text="this is the status bar")
        self.status.pack(fill="both", expand=True)

        self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
        self.some_title_frame.grid(row=0, column=1, sticky="ew")
        self.canvas_area.grid(row=1, column=1, sticky="nsew") 
        self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")

        self.root.grid_rowconfigure(1, weight=1)
        self.root.grid_columnconfigure(1, weight=1)

        self.root.mainloop()

Example()


另外,我强烈建议您不要删除用户调整窗口大小的功能。他们比你更清楚他们的要求是什么。如果正确使用
grid
pack
,GUI将完全调整大小

是的,但它并没有解决一个奇怪的错误,即当我在左侧添加内容时,左侧的菜单栏消失了。如果我这样做
self.test=tk.Label(self.menu_left_upper,text=“test”)
self.test.pack()
self.test.grid()
左侧的菜单上/下消失。您是否尝试给
self.test
一些填充(
padx
pady
),为什么会投反对票?有点困惑为什么有人会这么做。。。回答问题并获得计划:(谢谢,将对此进行测试。否决票不是我。因此,使用grid manager在顶层构建框架并管理它们,而使用pack manager管理框架的内容,是合法的吗?我尝试了
.grid\u propagate(False)的所有可能组合
:仅将其分配给
菜单左
,仅分配给
菜单左
,仅分配给
菜单左
或其组合。均未起作用。菜单和子帧正确显示,没有内容,但只要将
测试
标签添加到
菜单左
上,帧就会消失。Fo格式化是垃圾。请参见编辑。您需要将其放在
菜单左起之前
import Tkinter as tk

class Example():
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("some application")

        # menu left
        self.menu_left = tk.Frame(self.root, width=150, bg="#ababab")
        self.menu_left_upper = tk.Frame(self.menu_left, width=150, height=150, bg="red")
        self.menu_left_lower = tk.Frame(self.menu_left, width=150, bg="blue")

        self.test = tk.Label(self.menu_left_upper, text="test")
        self.test.pack()

        self.menu_left_upper.pack(side="top", fill="both", expand=True)
        self.menu_left_lower.pack(side="top", fill="both", expand=True)

        # right area
        self.some_title_frame = tk.Frame(self.root, bg="#dfdfdf")

        self.some_title = tk.Label(self.some_title_frame, text="some title", bg="#dfdfdf")
        self.some_title.pack()

        self.canvas_area = tk.Canvas(self.root, width=500, height=400, background="#ffffff")
        self.canvas_area.grid(row=1, column=1)

        # status bar
        self.status_frame = tk.Frame(self.root)
        self.status = tk.Label(self.status_frame, text="this is the status bar")
        self.status.pack(fill="both", expand=True)

        self.menu_left.grid(row=0, column=0, rowspan=2, sticky="nsew")
        self.some_title_frame.grid(row=0, column=1, sticky="ew")
        self.canvas_area.grid(row=1, column=1, sticky="nsew") 
        self.status_frame.grid(row=2, column=0, columnspan=2, sticky="ew")

        self.root.grid_rowconfigure(1, weight=1)
        self.root.grid_columnconfigure(1, weight=1)

        self.root.mainloop()

Example()