什么是比.grid()更好的Tkinter几何管理器

时间:2013-02-13 03:46:19

标签: python tkinter

我的投诉

我目前正在深入研究Tkinter GUI之前的“永远”,我发现.grid()几何管理器不合适有几个原因:

  1. 这些图是基于其中最大的小部件 - 这种相对性会导致不准确。

  2. 在Windows 7中,在Python 2.7.3上,程序似乎没有注意到我的行号,而是更喜欢使用小部件的顺序。

  3. 我的代码

    我目前正在使用真正的基本文本编辑器,我想在框架的顶部有多个按钮。我无法做到这一点,因为我的小部件被放置在占据屏幕中心的大量文本框的最左侧或右侧。

    ========Class __init__ Stuff============
    def widget(self):#Place widgets here
    
        #Save Button
        self.saveButton = Button (self, text = "Save", command = self.saveMe)
        self.saveButton.grid(column = 0, row = 0, sticky = W)
    
        #Open Button
        self.openButton = Button (self, text = "Open", command = self.openMe)
        self.openButton.grid(column = 0, row = 1, sticky = W)
        #Area where you write 
        self.text = Text (self, width = (root.winfo_screenwidth() - 20),
                          height = (root.winfo_screenheight() - 10))
        self.text.grid(row = 2)
    ==============Mainloop/Command Stuff============
    

    我的问题

    是否有另一种方式以更准确的方式使用.grid()几何管理器,或者我是否应该完全使用其他功能?

    谢谢!

4 个答案:

答案 0 :(得分:15)

您可以使用3个几何管理器 - gridpackplace。第三是最普遍的,但也很难使用。我更喜欢grid。请注意,您可以将小部件放在其他小部件中 - 或者您可以指定columnspan。因此,如果您想获得以下布局:

  -------------------------
  |    Button1  | Button2 |
  -------------------------
  |     Big Widget        |
  -------------------------

使用.grid有两种规范方法。第一种方法是columnspan

import Tkinter as Tk
root = Tk.Tk()
b1 = Tk.Button(root,text="Button1")
b1.grid(row=0,column=0)
b2 = Tk.Button(root,text="Button2")
b2.grid(row=0,column=1)
big_widget = Tk.Canvas(root)
big_widget.grid(row=1,column=0,columnspan=2)

*请注意,还有一个完全类似的rowspan选项。

第二种方法是使用Frame按住按钮:

import Tkinter as Tk
root = Tk.Tk()
f = Tk.Frame(root)
f.grid(row=0,column=0)
#place buttons on the *frame*
b1 = Tk.Button(f,text="Button1")
b1.grid(row=0,column=0)
b2 = Tk.Button(f,text="Button2")
b2.grid(row=0,column=1)

big_widget = Tk.Canvas(root)
big_widget.grid(row=1,column=0)  #don't need columnspan any more.

此方法 SUPER 对于创建复杂的布局非常有用 - 我不知道如何在不使用Frame这样的对象的情况下创建复杂的布局...

答案 1 :(得分:5)

“最佳”几何管理器取决于您想要做什么,没有几何管理器最适合所有情况。对于您在这个特定情况下尝试做的事情,打包可能是更好的选择。另请注意,应用程序中可能有多个“最佳”。在应用程序的不同部分使用网格和包是很正常的。我很少创建一个GUI,我不使用网格和包。很少,我也使用地方。

pack擅长将事物放在单行和单列中。例如,工具栏是使用pack的理想选择,因为您希望所有按钮都对齐到左侧。顾名思义,网格最适合您想要固定的行和列。在网格和包都不会发生的极少数情况下,place非常有用,因为它允许您将小部件放在精确的固定或相对位置。

我的建议是将应用程序小部件分成组,并为每个组使用正确的几何管理器。在您的情况下,您有两个逻辑组:顶部的工具栏,以及底部的文本小部件和滚动条组合。所以,从两帧开始。由于工具栏位于顶部,文本小部件位于下方,因此打包效果最佳。

toolbar = tk.Frame(...)
main = tk.Frame(...)
toolbar.pack(side="top", fill="x", expand=False)
main.pack(side="bottom", fill="both", expand=True)

以上现在为您提供了两个易于独立修改的区域。

对于工具栏,包装也是最自然的。但是,在这种情况下,您需要左侧的按钮而不是顶部或底部的按钮:

b1 = tk.Button(toolbar, ...)
b2 = tk.Button(toolbar, ...)
b1.pack(side="left")
b2.pack(side="left")
...

最后,底部区域。您的示例代码不显示滚动条,但我认为在某些时候您会想要添加它们。如果您同时使用水平和垂直滚动条,网格效果很好。我会这样说出来:

hsb = tk.Scrollbar(main, ..., orient="horizontal", ...)
vsb = tk.Scrollbar(main, ..., orient="vertical", ...)
text = tk.Text(main, ...)
vsb.grid(row=0, column=1, sticky="ns")
hsb.grid(row=1, column=0, sticky="ew")
text.grid(row=0, column=0, sticky="nsew")
main.grid_rowconfigure(0, weight=1)
main.grid_columnconfigure(0, weight=1)

最后一部分很重要 - 你总是需要给至少一行和一列赋予权重。这会告诉网格调整窗口大小时哪些行和列应该增长和缩小。

答案 2 :(得分:0)

我发现place经理在所有三个中都是最直观和准确的,因为可以指定位置和大小的绝对长度和相对长度的组合:

mywidget.place(x=..., y=..., width=..., height=...) # absolute
mywidget.place(relx=..., rely=..., relwidth=..., relheight=...) # relative

# combination
pad_left=5
pad_right=5
pad_top=5
pad_bottom=5
mywidget.place(relx=0, x=pad_left, rely=0, y=pad_top,\
       relwidth=1, width=-pad_left-pad_right,\
       relheight=1, height=-pad_top-pad_bottom, anchor="e") # use the whole space except some padding

出于某种原因,.place经理看起来并不是很受欢迎,但我发现定义你的小部件如何移动并在调整父窗口大小时调整大小是一件特别好的工作。

为了简化复杂窗口的构建,我有时会使用一个函数(以模仿我想的网格行为)来帮助垂直放置,例如:

def offset_y(line_no):
    if line_no == 0:
        return 0
    else:
        return height_label + (line_no - 1)*height_button

mylabel.place(..., y=offset_y(0))
mybtn1.place(..., y=offset_y(1))
etc.

垂直打包Label,然后打包一系列按钮。 (当然,.pack经理可以在这种情况下使用,但我更喜欢.place经理的原因是为了更准确地理解当调整窗口大小时事物会如何移动。)

答案 3 :(得分:-2)

而不是行,列......等,你可以使用坐标。

它可能比其他人容易。

示例:

from Tkinter import*
root=Tk()
Button(root,text="HI").grid(padx=100,pady=50)
root.mainloop()

通过更改padx和pady值来尝试自己。