【问题标题】:Some elementary tkinter questions一些基本的 tkinter 问题
【发布时间】:2018-02-14 15:55:49
【问题描述】:

我有几个关于几何管理器的问题:

(a) grid 几何管理器如何确定行和列?我的意思是,网格管理器如何将主小部件索引到行和列?

我对此有很多困惑 - 当您输入 a.grid(row=100,column=100)a.grid(row=0, column=0) 时,结果完全一样!

另外,您可以使用 grid 将一个小部件放在最右上方,将一个小部件放在最左下方,并且中间空间为空吗?

(b) pack 几何管理器中的 fillexpand 有什么区别?

另外,当我创建a = Text(root, width=100, height=100),然后输入a.pack(side=TOP)a.pack(side=LEFT)a.pack(side=RIGHT)时,为什么文本框总是位于页面的底部

【问题讨论】:

  • side部分,两个widget打包后效果可见。 pack(side=TOP) 将导致小部件从上到下堆叠(默认行为),而 pack(side=LEFT) 将导致它们从左到右堆叠。
  • @Rightleg 对不起,我不太明白你的意思。你是说当我打包文本后打包另一个小部件时,实际定位将可见吗? (另外,对我的其他问题有什么想法吗?)
  • 是的,side 参数指示小部件应如何相对于另一个定位。

标签: python tkinter


【解决方案1】:

a) grid 几何管理器仅将空间分配给实际具有某些内容的行和列。因此,如果您只有一个小部件,则选择哪一行和哪一列都没有关系,网格实际上只有一个单元格(也就是说,除非您使用grid_rowconfiguregrid_columnconfigure 指定其他选项,更多关于@ 987654321@ 和 here)。

b) 使用pack 几何管理器,fill 选项指示小部件必须扩展自己的大小以填充几何管理器分配的空间。如果您不指定它,则小部件周围可能会有一些空白空间,例如,如果您将多个小部件排成一排并且有些比其他小部件高。另一方面,expand 选项会影响几何管理器分配给小部件的空间量;如果您不指定它,它将获得尽可能少的空间,否则任何剩余空间将分配给所有设置了expand 的小部件(更多信息here)。所以它们是真正独立的东西,一个影响小部件本身的大小,另一个影响它接收的窗口空间量。

至于你的最后一个问题,也许你可以提供一个minimal example来显示你的问题。

【讨论】:

    【解决方案2】:

    基本上,使用.grid() 方法,如果您在(0, 0) 位置创建一个小部件并且下一个小部件位于(100, 100) 位置,那么系统会将第二个小部件放置在看似(1, 1) 的位置。这是因为第二个小部件依次位于“下一个位置”。你可以认为(1, 1)(99, 99)的位置仍然存在但无限小,所以(100, 100)看起来就在(0, 0)旁边,示例如下:

    from tkinter import *
    
    root = Tk()
    
    label1 = Label(root, text="Col0, Row0")
    label2 = Label(root, text="Col100, Row100")
    
    label1.grid(column=0, row=0)
    label2.grid(column=100, row=100)
    
    root.mainloop()
    

    关于能够使用.grid() 将对象放置在对角,这是可能的,并且可以使用rowconfigurecolumnconfigureweight 属性的组合以及sticky 属性的组合来完成在小部件上使用.grid()。见下文:

    from tkinter import *
    
    root = Tk()
    
    label1 = Label(root, text="1")
    label2 = Label(root, text="2")
    
    label1.grid(column=0, row=0, sticky="NW")
    label2.grid(column=1, row=1, sticky="SE")
    
    root.columnconfigure(0, weight=1)
    root.rowconfigure(0, weight=1)
    
    #Giving the rows and columns a weight that is not equal to 0
    #means that the rows and columns expand to fill the space in the window.
    #Then we assign a sticky value to the labels,
    #to position them where we need them in the cell.
    
    root.columnconfigure(1, weight=1)
    root.rowconfigure(1, weight=1)
    
    root.mainloop()
    

    如果您正在寻找有关 .pack() 的不同属性如何工作的更多信息,我前段时间写了这篇文章作为另一个问题的答案,它应该有助于了解使用 .pack() 的基础知识:

    from tkinter import *
    
    root = Tk()
    top = Toplevel()
    top.withdraw()
    var1 = StringVar(root)
    var1.set("top")
    var2 = StringVar(root)
    var2.set("none")
    var4 = StringVar(root)
    var4.set("center")
    var3 = BooleanVar(root)
    
    def command(top, var1, var3, var2):
        top.destroy()
        top = Toplevel()
        top.geometry("500x500")
        Label(top, text="Welcome home").pack()
        Button(top, text="Button1").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
        Button(top, text="Button2").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
        Button(top, text="Button3").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
        Button(top, text="Button4").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
    
    option1 = OptionMenu(root, var1, "top", "left", "bottom", "right")
    check1 = Checkbutton(root, variable=var3, text="Expand?")
    option2 = OptionMenu(root, var2, "none", "x", "y", "both")
    option3 = OptionMenu(root, var4, "center", "n", "ne", "e", "se", "s", "sw", "w", "nw")
    button1 = Button(root, text="Render", command=lambda:command(top, var1, var3, var2))
    
    option1.pack()
    check1.pack()
    option2.pack()
    option3.pack()
    button1.pack()
    
    root.mainloop()
    

    将其放入您选择的编辑器中并使用它。


    我还想指出,Stack Overflow 并不是真正适合此类问题的地方,我建议在使用 SO 之前查找有关您想知道的任何内容的文档。

    例如,最好的 tkinter 文档(在我看来)是: http://effbot.org/tkinterbook/

    【讨论】:

      【解决方案3】:

      我将尽我所能解释导致您对几何管理器感到困惑的原因。

      (a) 网格几何管理器如何确定行和列?我的意思是,网格管理器如何将主小部件索引到行和列?

      行和列是按照您的预期确定的。您对a.grid(row=100,column=100)a.grid(row=0, column=0) 出现相同的问题是由于行和列的性质。如果一行或一列中没有任何小部件,则该行或列将折叠成空。直到此时有东西放在里面。

      因此,当您定义一个网格以在 row=1, column=1 处包含一个小部件时,您会期望在您的脑海中得到类似的东西。

      *--------*--------*
      |        |        |
      |        |        |
      |        |        |
      *--------*--------*
      |        | row=1  |
      |        | column |
      |        |  =1    |
      *--------*--------*
      

      但是,因为第 0 行和第 0 列中没有小部件,所以它们会明显折叠成任何东西,你会得到:

      *--------*
      | row=1  |
      | column |
      |  =1    |
      *--------*
      

      其他 3 个单元格仍然存在,它们只是没有被填充的空间,因此它们尽可能小,结果是明显缺少单元格。

      你可以在最右上方放置一个小部件,在最左下方放置一个小部件,中间的空间是空的吗,使用网格?

      是的,你可以。会发生与上面相同的事情,并且看起来中间单元格消失了,但是您可以向网格添加更多参数,以使其仍然显示为 3 x 3。例如,请参见以下代码:

      我们可以改变行或列的权重来控制网格行为。

      from tkinter import *
      
      class Application():
          def __init__(self, master):
      
              self.master = master
              self.master.geometry("400x400")
              # the below column and row weights allow us to control the behavior of the grid.
              # setting the weight to 0 means the row or column will not resize at all
              # setting the number to 1 or higher will allow the row or column to resize with the window
              # what this does is allow us to keep widgets where we want them by manipulating the weights.
              self.master.columnconfigure(0, weight = 0)
              self.master.columnconfigure(1, weight = 1)
              self.master.columnconfigure(2, weight = 0)
              self.master.rowconfigure(0, weight = 0)
              self.master.rowconfigure(1, weight = 1)
              self.master.rowconfigure(2, weight = 0)
      
              top_left_label = Label(self.master, text="I am at the top left")
              top_left_label.grid(row=0, column=0)
      
              bottom_right_label = Label(self.master, text="I am at the bottom right")
              bottom_right_label.grid(row=2, column=2)
      
      root = Tk()
      Application(root)
      root.mainloop()
      

      包几何管理器中的填充和扩展有什么区别?

      这个问题已经被问过几次了,这里有一个关于这个主题的Question/Answer 的链接。

      以下是与该主题相关的简短回答:

      本质上,fill 选项告诉 tkinter,您要填充小部件可用空间的 x 轴或 y 轴或两个方向。这意味着,如果一个框架具有设定的大小,并且您使用 fill = BOTH 选项在该框架中放置一个按钮,那么该按钮将填充该框架的大小,如果该框架被调整大小,那么该按钮也会如此。

      expand 选项告诉管理器填充给定框架/窗口中所有小部件之间的所有可用空间。因此,如果其他小部件也分配了展开选项,它们将平均共享空间。请记住,这是一个简单的解释,您应该阅读文档以了解完整情况。

      当我创建 a = Text(root, width=100, height=100) 时,然后键入 a.pack(side=TOP) 或 a.pack(side=LEFT) 或 a.pack(side=RIGHT),为什么文本框总是位于页面底部?

      简单的答案是没有。

      如果您看到这种情况,那么它是由其他原因引起的,而不是您打包小部件的方式。

      查看下面的示例代码并尝试调整窗口大小。您将看到每个包选项的工作原理。

      from tkinter import *
      
      class Application():
          def __init__(self, master):
      
              self.master = master
              self.master.geometry("400x400")
              Text(root, width=10, height=4).pack(side=TOP)
              Text(root, width=10, height=4).pack(side=LEFT)
              Text(root, width=10, height=4).pack(side=RIGHT)
              Text(root, width=10, height=4).pack(side=BOTTOM)
      
      
      root = Tk()
      Application(root)
      root.mainloop()
      

      结果:

      如果您还有其他问题,请告诉我。

      如果有人希望我扩展我的任何答案,请告诉我,我会添加它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-14
        • 2012-05-18
        • 2011-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多