【问题标题】:Tkinter pack method confusionTkinter pack 方法混淆
【发布时间】:2019-08-07 08:40:15
【问题描述】:

我不明白为什么包管理器不允许您在顶部打包的小部件下方左右打包。以下代码的预期输出将是

 A
 B
C D 
 E

但它只显示:

 A
 B
C D
import tkinter as tk

root = tk.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.state('zoomed')
root.geometry("%dx%d+0+0" % (w-15, h-75))
A = tk.LabelFrame(root,text='A', bd=2)
B = tk.LabelFrame(root,text='B', bd=2)
C = tk.LabelFrame(root,text='C', bd=2)
D = tk.LabelFrame(root,text='D', bd=2)
E = tk.LabelFrame(root,text='E', bd=2)

A.pack(fill=tk.BOTH, expand=tk.TRUE)
B.pack(fill=tk.BOTH, expand=tk.TRUE)
C.pack(side=tk.LEFT,fill=tk.BOTH, expand=tk.TRUE)
D.pack(side=tk.RIGHT,fill=tk.BOTH, expand=tk.TRUE)
E.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=tk.TRUE)

root.mainloop()

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    简而言之,打包程序并非旨在直接创建您要创建的布局。你可以做到,但它需要一些额外的帧。在这种特殊情况下,您显然想创建一个网格,grid 可以说是更好的选择。

    在解释为什么会这样之前,让我提出一个解决方案。创建另一个名为“CD”的框架,用于容纳CD。然后您可以将C 打包到左侧,将D 打包到右侧,然后将此框架放在B 下方。这就是您使用加壳程序达到预期结果的方式。

    A = tk.LabelFrame(root,text='A', bd=2)
    B = tk.LabelFrame(root,text='B', bd=2)
    CD = tk.Frame(root)
    C = tk.LabelFrame(CD,text='C', bd=2)
    D = tk.LabelFrame(CD,text='D', bd=2)
    E = tk.LabelFrame(root,text='E', bd=2)
    
    C.pack(side=tk.LEFT,fill=tk.BOTH, expand=tk.TRUE)
    D.pack(side=tk.RIGHT,fill=tk.BOTH, expand=tk.TRUE)
    
    A.pack(fill=tk.BOTH, expand=tk.TRUE)
    B.pack(fill=tk.BOTH, expand=tk.TRUE)
    CD.pack(fill=tk.BOTH, expand=tk.TRUE)
    E.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=tk.TRUE)
    

    解释封隔器

    打包器通过在未分配空间的一侧保留一块空间来工作。 这个分配的空间在将小部件打包到顶部或底部时占据了未分配空间的整个宽度,在左侧或右侧打包时占据了整个高度。这是一个重要的细节。

    让我试着用一些截图来描述它。在所有情况下,以下屏幕截图均未显示帧,它们显示了打包程序管理的已分配和未分配空间量。

    当您沿顶部包装A(如果您不指定边,则顶部是默认值),为根窗口的整个宽度保留一块空间。而且因为你把它打包到顶部,所以唯一剩余的空间在A下面。从此时起,A 的左侧或右侧都不能打包。

    (其实你可以通过一些高级选项把东西放在左边或右边,但这超出了本文的描述范围)

    当您将 B 沿顶部打包时,唯一可用空间位于 A 下方。同样,因为您将它沿顶部打包,所以在打包 B 之后,现在唯一可用的可用空间将低于 B

    当您将C 沿左侧打包时,会为剩余空间的整个高度保留一块空间。这意味着任何东西都不能放在C 下面。所有剩余空间都在C 的右侧,B 的下方。

    1. 打包D时,必须到C右侧,B下方。因为你把它打包到右边,它会保留D上方和下方的所有剩余垂直空间。

    当你把E放在底部时,它唯一能去的地方是B下面,C右边,D左边。

    由于封隔器的性质是沿一侧分配所有空间,因此当所有小部件放置在同一轴上时(无论是垂直堆叠还是水平堆叠),封隔器的工作效果最佳。当您想像使用CD 一样切换轴时,通常最好将它们放在单独的框架中。在该框架内,您可以将小部件从左到右放置,但该框架可以与其他小部件一样保持在自上而下的轴上。

    注意:这是您的代码中实际发生的情况:E 被挤压在 CD 之间。由于各种原因它不可见,但如果你要给它一个明确的大小和颜色,它就会显示出来。

    更多信息

    packer算法的权威描述见tcl/tk man pages for pack

    【讨论】:

    • 感谢您的彻底回应。我想我会坚持使用 pack 方法而不是将我的代码更改为网格,为 CD 添加额外的 LabelFrame 不是最干净的,但它会做。
    • @Cr1064:使用附加框架并没有什么“不干净”的地方。这正是框架的用途。要使用pack 获得所需的布局,您必须使用框架。因此,您正在以正确的方式为您选择使用的布局管理器使用正确的小部件。
    【解决方案2】:

    一种解决方法是将 C + D 框架打包到临时 LabelFrame 中,然后您可以将其打包到 B 下。

    import tkinter as tk
    
    root = tk.Tk()
    w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    root.state('zoomed')
    root.geometry("%dx%d+0+0" % (w-15, h-75))
    A = tk.LabelFrame(root,text='A', bd=2)
    B = tk.LabelFrame(root,text='B', bd=2)
    
    temp = tk.LabelFrame(root)
    
    C = tk.LabelFrame(temp,text='C', bd=2)
    D = tk.LabelFrame(temp,text='D', bd=2)
    E = tk.LabelFrame(root,text='E', bd=2)
    
    A.pack(fill=tk.BOTH, expand=tk.TRUE)
    B.pack(fill=tk.BOTH, expand=tk.TRUE)
    C.pack(side=tk.LEFT,fill=tk.BOTH, expand=tk.TRUE)
    D.pack(side=tk.RIGHT,fill=tk.BOTH, expand=tk.TRUE)
    temp.pack(expand=tk.TRUE, fill=tk.BOTH)
    E.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=tk.TRUE)
    
    root.mainloop()
    

    【讨论】:

      【解决方案3】:

      tkinter pack 是所有三个几何管理器之一。它有助于指定所有 tkinter 小部件的几何形状。这是代码示例。

      from tkinter import * 
      
      window = Tk()
      
      Label(window,text = "Text").pack()
      
      window.mainloop()
      

      欲了解更多信息,请参阅tkinter pack上的本教程

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-09
        • 2013-03-01
        • 2011-09-19
        • 2018-04-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多