2013-02-13 60 views
4

我的投诉什么是更好的Tkinter几何经理比.grid()

我目前钻研比“以往”前进入Tkinter的GUI深,我已经找到了.grid()几何管理是不够的几个原因:

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

  2. 在Windows 7上的Python 2.7.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()几何管理的方式,更准确的,或者我应该完全使用其他功能?

谢谢!

+0

你对windows的评论不是“heeding your row numbers”是不正确的。几十年来,网格几何管理器已被证明在所有平台上都可以100%运行。我并不是说你的代码不是行为不端,这只是因为你认为它的原因而不是行为不端。 – 2013-02-13 12:07:35

回答

14

有3个几何管理器,您可以使用 - grid,packplace。第三种是最一般的,但也很难使用。我更喜欢grid。请注意,您可以将部件等部件的内部 - 或者你可以指定columnspan。所以,如果你想获得以下布局:

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

有2种规范的方式使用.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对象是这样的...

+0

好的....所以你使用Tk.Canvas而不是Tk.Text,对吗?另外,如何使用.place()以及为什么它是最普通/准确的(含义不明确)(我的意思是模糊的) – xxmbabanexx 2013-02-13 03:59:19

+0

,使用'.place',您指定了要放置该小部件的确切坐标。就我而言,那将是一场维护**噩梦**,而且几乎不值一提。 - 是的,我说'画布'而不是'文本' - 我只需要选择一个通常比'Button'小部件所需空间大得多的部件;-) – mgilson 2013-02-13 04:00:39

+0

+1 - 根据我的经验许多不同的GUI工具包和几何管理器,使用一个非常简单的布局管理器,并将不同的组嵌套到目前为止最好。所有那些更复杂的几何图形(我说的是Swing和所有不同的管理者)都很难使用,并且没有给你任何你无法用嵌套方法得到的东西。 – Voo 2013-02-13 04:06:18

5

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

pack擅长将东西放在单行和单列中。例如,工具栏是使用包的最佳例子,因为您希望所有按钮都对齐到左侧。正如其名称所暗示的,当您想要固定的行和列时,最好使用网格。在网格和包装都不会做的罕见情况下,地点很有用,因为它允许您将小部件放置在精确的固定位置或相对位置。

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

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) 

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

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. 

垂直收拾标签然后是一系列按钮。 (当然,在这种情况下可以使用.pack管理器,但我更喜欢.place管理器的原因是为了更准确地理解窗口大小调整时的情况。

+0

我不明白你对准确性的评论。例如,当我使用包和网格时,我确切知道他们将如何表现。在这方面如何更准确?至于为什么大多数人不使用场所,这可能是因为它更复杂:它需要你自己做很多数学。包和网格都为您处理大部分数学问题。 – 2013-04-06 15:52:09

+1

我想我喜欢'place'就是坐标系。 @Bryan Oakley:在这个意义上说是准确的:我确切地知道我在哪里放置我的小部件,以及我在框架内以绝对坐标或相对坐标给出它的大小。我可以像这样添加我的所有小部件。我不特别喜欢关于'pack'的东西,就是需要一个不可见的'Frame'层次结构来对小部件进行分组。我不特别喜欢'grid',当窗口大小调整应该移动窗口部件但不修改窗口大小时,必须使用'buffer'(不可见)行/列来提供可扩展'填充'。但是也许我错过了某事? – 2013-04-07 16:15:13

-2

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

它可能比其他人更容易。

例:

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

通过改变padx和pady值试试吧youself。

相关问题