【问题标题】:How to pack a tkinter widget underneath an existing widget that has been packed to the left side?如何在已打包到左侧的现有小部件下方打包 tkinter 小部件?
【发布时间】:2009-09-28 04:25:57
【问题描述】:

我正在尝试编写一个基本的 Tkinter GUI,它在顶部有一个 Text 小部件,然后在其下方左对齐一个 Button 小部件,然后在按钮下方有另一个 Text 小部件。我遇到的问题是,在将Button 小部件打包到左侧之后,当我去打包第二个Text 小部件时,它将它放在右侧按钮旁边,而不是按钮下方。无论我为第二个Text 小部件设置side 参数是什么,都会发生这种情况下面是一段简单的代码来演示这种行为:

from Tkinter import *

root = Tk()

w = Text(root)
w.pack()

x = Button(root, text="Hi there!")
x.pack(side=LEFT)

y = Text(root)
y.pack(side=BOTTOM)

root.mainloop()

那么我该如何设置第二个Text 小部件,使其显示在按钮下方,而不是右侧?

【问题讨论】:

  • before 方法的 before 关键字参数可能会有所帮助。

标签: python widget tkinter pack


【解决方案1】:

使用 Mosaic Canvas Widget Sets internals(与 Tk 非常相似)的方式与 WebView 相同。诀窍是第二个相同名称的框架对象作为块级浮点(内联:块;)用于放置在它之后的所有内容,并且已经调用“fr”的所有内容都将在其中自动重新开始。

您可以有很多这样的 TOP 对齐小部件,只需添加另一个相同的名为 Frame 的地方,您想在 side=LEFT 之间进行中断。在底部之后也可以使用。

fr=Frame(root)
fr.pack(fill=X, side=TOP)

block1=Label(fr)
block1.pack(side=LEFT)

block2=Label(fr)
block2.pack(side=LEFT)

block3=Button(fr)
block3.pack(side=LEFT)

# NAME IT THE SAME ID NAME AS THE FIRST MAIN FRAME...
fr=Frame(root)
fr.pack(fill=X, side=TOP)

# These NOW jump into the second Frame breaking the side=LEFT in new Frame
block4=Label(fr) 
block4.pack(side=LEFT)

block5=Label(fr)
block5.pack(side=LEFT)

# AND THEY CONTINUE GOING side=LEFT AFTERWARDS.

【讨论】:

    【解决方案2】:

    布局问题一般有两种解决方案:

    1. 切换到使用网格。像你想要完成的那样做布局变得非常容易。 Grid 可以解决大约 95% 的布局问题(想想就觉得不可思议——Tk 只需一个管理器就可以完成大多数工具包需要六个才能完成的工作!)

    2. 使用多个帧。如果某些小部件需要从上到下堆叠,有些从左到右堆叠,则无法始终将所有内容打包在一个框架中。对布局的从上到下部分使用一个框架,对从左到右的内容使用其他框架。

    还要意识到小部件不必是它们被打包/网格化的小部件的子级。您可以使用“in”参数将小部件放在其他容器中而不是它们的父容器中。

    例如,在您的具体示例中,您可以创建三个框架,顶部、中间、底部。将这些从上到下打包在顶层窗口中。然后,您可以将第一个文本小部件放在顶部,将一个或多个水平按钮放在中间,将另一个文本小部件放在底部。

    这种方法的优势在于它使将来更改布局变得更加容易(根据我的经验总是在某些时候发生)。您不必重新设置任何小部件的父级,只需将它们打包/放置/网格在其他容器中。

    在您的简短示例中,它没有太大区别,但对于复杂的应用程序,此策略可以挽救生命。

    我最好的建议是:布局不是事后的想法。做一些计划,甚至可能花五分钟在一些方格纸上画画。首先确定应用程序的主要区域,并为每个区域使用框架或其他容器(窗格窗口、笔记本等)。一旦你有了这些,对每个部分执行相同的分而治之的方法。这使您可以为应用程序的不同部分使用不同类型的布局。工具栏采用水平布局,表单可能采用垂直布局等。

    【讨论】:

      【解决方案3】:

      我最初误解了包装的工作原理,并没有意识到当我做x.pack(side=LEFT) 时整个左侧都被“认领”了。我在阅读this 后发现,Alex 在这里的回答是,我并没有真正将x 打包到左侧,而是将其 锚定 放在左侧,使用anchor=W(W 代表西部)而不是 side=LEFT。我修改后的代码 sn-p 看起来像这样:

      from tkinter import *
      
      root = Tk()
      
      w = Text(root)
      w.pack()
      
      x = Button(root, text="Hi there!")
      x.pack(anchor=W)
      
      y = Text(root)
      y.pack(side=BOTTOM)
      
      root.mainloop()
      

      这样x 不再“声称”左侧,它只是在其空间块内与左侧(或西部)对齐。

      【讨论】:

        【解决方案4】:

        打包按照 .pack 方法被调用的顺序进行,所以一旦 x “认领”了左侧,就是这样 - 它将占用其父级的左侧部分,其父级中的其他所有内容都将归其所有正确的。您需要一个框架来“调解”,例如....:

        from Tkinter import *
        
        root = Tk()
        
        w = Button(root, text="Mysterious W")
        w.pack()
        
        f = Frame(root)
        x = Button(f, text="Hi there!")
        x.pack()
        
        y = Button(f, text="I be Y")
        y.pack(side=BOTTOM)
        
        f.pack(side=LEFT)
        
        root.mainloop()
        

        (将 Texts 更改为 Buttons 只是为了更直接地显示布局 - 这台 Mac 上的 Tkinter 在获得焦点之前不会清楚地显示 Texts,但 Buttons 非常清晰;-)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-25
          • 2016-11-13
          • 1970-01-01
          • 2017-09-08
          • 2018-08-25
          • 1970-01-01
          • 2020-09-02
          • 1970-01-01
          相关资源
          最近更新 更多