2014-11-23 61 views
0

在Mac OS上使用python 3.4.1我试图在称为'lowerframe'的子框架中使用网格几何管理器平均分配标签和条目小部件。tkinter网格:在框架高度和宽度上分布行和列

我现在MWE如下所示:

#!/usr/bin/env python3 

from tkinter import * 
from tkinter import ttk 

class Window(Frame): 
    def __init__(self, master=None): 
     Frame.__init__(self, master) 
     # create master window 
     self.master = master 

     # create root window on initialization 
     self.create_rootwindow() 

    def create_rootwindow(self): 
     self.master.title("GUI") 
     self.master.geometry("1024x748") 
     self.master.resizable(width=FALSE, height=FALSE) 

     self.create_upperframe() 
     self.create_lowerframe() 
     self.create_inputentries() 
     self.create_btnframe() 
     self.create_inputbtn() 

    def create_upperframe(self): 
     self.upperframe = Frame(self.master, width=980, height=490) 
     self.upperframe.config(background="#339900") 
     self.upperframe.place(x=20, y=10) 

    def create_lowerframe(self): 
     self.lowerframe = Frame(self.master, width=830, height=200) 
     self.lowerframe.config(background="#336699") 
     self.lowerframe.place(x=20, y=530) 

    def create_inputentries(self): 
     self.create_lowerframe() 

     parameternames = [ 
      ('a', 'U'), ('b', 'U'), ('c', 'U'), ('d', 'U'), ('e', 'U'), 
      ('f', 'U'), ('g', 'U'), ('h', 'U'), ('i', 'U'), ('j', 'U'), 
      ('k', 'U'), ('l', 'U'), ('m', 'U'), ('n', 'U'), ('o', 'U'), 
      ('p', 'U'), ('q', 'U'), ('r', 'U'), ('s', 'U'), ('t', 'U')] 

     for i, data in enumerate(parameternames): 
      r = i % 5 
      c = (i // 5) * 3 
      Label(self.lowerframe, text=data[0]).grid(row=r, column=c, pady=4, padx=0) 
      Entry(self.lowerframe, width=10).grid(row=r, column=c+1, pady=4, padx=0) 
      Label(self.lowerframe, text=data[1]).grid(row=r, column=c+2, pady=4, padx=0) 

    def create_btnframe(self): 
     self.btnframe = Frame(self.master, width=130, height=200) 
     self.btnframe.place(x=870, y=530) 

    def create_inputbtn(self): 
     self.create_btnframe() 

     startanalysis_btn = Button(self.btnframe, text="Start Analysis", width=12, command=self.do_nothing) 
     startanalysis_btn.place(x=0, y=0) 

     abortanalysis_btn = Button(self.btnframe, text="Abort Analysis", width=12, command=self.do_nothing) 
     abortanalysis_btn.place(x=0, y=50) 

     resetanalysis_btn = Button(self.btnframe, text="Reset Analysis", width=12, command=self.do_nothing) 
     resetanalysis_btn.place(x=0, y=100) 

     showresults_btn = Button(self.btnframe, text="Show Results", width=12, command=self.do_nothing) 
     showresults_btn.place(x=0, y=200, anchor=SW) 

    def do_nothing(self): 
     pass 

root = Tk() 

app = Window(root) 

root.mainloop() 

正如你所看到的,每个下部,蓝框控件(称为“lowerframe”)的“设置”由一个标签与说​​明书(这里'a'到't'),一个输入小部件和另一个标签小部件,其输入值的相应单位(这里是所有标签的'U')。

使用这些“集合”我需要创建五行和4个“设置列”(目前使用网格几何管理器的12列)。我的目标是将这些行和“设置列”分配到指定高度和宽度的底框。

- 编辑:我上传了sketch到我的Dropbox文件夹,显示结果应该如何。

回答

2

您编写代码的方式使其很难修改。首先,根据经验,你绝不应该使用place。根本没有必要,因为packgrid提供更多的功能。

其次,作为一个经验另一个规则,家长应该负责布置其子 - 没有,创建一个框架的功能也呼吁gridpack,或place把自己在其父。如果你决定改变你的布局,你最终不得不改变一堆功能。

最后,当使用网格时,如果您希望它们增长以填充其包含的窗口,则需要给出行和列“重量”。

这是我会怎么重写代码:

from tkinter import * 

class Window(Frame): 
    def __init__(self, master=None): 
     Frame.__init__(self, master) 
     # create master window 
     self.master = master 

     # create root window on initialization 
     self.create_rootwindow() 

    def create_rootwindow(self): 
     self.master.title("GUI") 
     self.master.geometry("1024x748") 

     self.create_upperframe() 
     self.create_lowerframe() 
     self.create_inputentries() 
     self.create_btnframe() 
     self.create_inputbtn() 

     self.upperframe.pack(side="top", fill="both", expand=True, padx=4) 
     self.lowerframe.pack(side="left", fill="both", expand=True, padx=4, pady=4) 
     self.btnframe.pack(side="right", fill="both", padx=4, pady=4) 

    def create_upperframe(self): 
     self.upperframe = Frame(self.master, width=980, height=490) 
     self.upperframe.config(background="#339900") 

    def create_lowerframe(self): 
     self.lowerframe = Frame(self.master, width=830, height=200) 
     self.lowerframe.config(background="#336699") 

    def create_inputentries(self): 
     self.create_lowerframe() 

     parameternames = [ 
      ('a', 'U'), ('b', 'U'), ('c', 'U'), ('d', 'U'), ('e', 'U'), 
      ('f', 'U'), ('g', 'U'), ('h', 'U'), ('i', 'U'), ('j', 'U'), 
      ('k', 'U'), ('l', 'U'), ('m', 'U'), ('n', 'U'), ('o', 'U'), 
      ('p', 'U'), ('q', 'U'), ('r', 'U'), ('s', 'U'), ('t', 'U')] 

     for i, data in enumerate(parameternames): 
      r = i % 5 
      c = (i // 5) * 3 
      Label(self.lowerframe, text=data[0]).grid(row=r, column=c, pady=4, padx=0, sticky="nsew") 
      Entry(self.lowerframe, width=10).grid(row=r, column=c+1, pady=4, padx=0, sticky="ew") 
      Label(self.lowerframe, text=data[1]).grid(row=r, column=c+2, pady=4, padx=0, sticky="nswe") 

      self.lowerframe.grid_columnconfigure(c+1, weight=1) 


    def create_btnframe(self): 
     self.btnframe = Frame(self.master, width=130, height=200) 

    def create_inputbtn(self): 
     self.create_btnframe() 

     startanalysis_btn = Button(self.btnframe, text="Start Analysis", width=12, command=self.do_nothing) 
     abortanalysis_btn = Button(self.btnframe, text="Abort Analysis", width=12, command=self.do_nothing) 
     resetanalysis_btn = Button(self.btnframe, text="Reset Analysis", width=12, command=self.do_nothing) 
     showresults_btn = Button(self.btnframe, text="Show Results", width=12, command=self.do_nothing) 

     startanalysis_btn.pack(side="top", fill="x") 
     abortanalysis_btn.pack(side="top", fill="x") 
     resetanalysis_btn.pack(side="top", fill="x") 
     showresults_btn.pack(side="top", fill="x") 

    def do_nothing(self): 
     pass 

root = Tk() 
app = Window(root) 
root.mainloop() 

事情需要注意:

  • 我已经更换了的place所有使用与pack(虽然grid将工作一样好)
  • 我已将pack的主要区域分组在一起
  • 我将pack按钮分组在一起,使得可视化和修改更容易。
  • 我已经为底部框架中具有条目窗口小部件的列添加了权重。这会导致这些列增长或缩小以填充任何额外空间
  • 我已将设置可调整大小设置为false。一般来说,我认为应该允许用户选择GUI的大小。此外,它还说明通过使用pack和/或grid而不是place,您可以在不做任何额外工作的情况下获得适当的调整行为。如果您真的认为自己比用户更了解,那么可以重新加入。

代码现在具有良好的调整行为,入口小部件的网格展开以填充其容器,并且功能耦合不太紧密因为创建框架的功能不必知道框架将如何显示。

+0

这解决了我的一半任务。小部件现在分布在框架的高度和宽度上。不过,我想指定条目窗口小部件的宽度,并在每组“label-entry-label”之间获得一些自动分配的空间。目前,我无法为条目窗口部件指定宽度,或者至少在当前设置中不会生效。我上传了一个[sketch](https://dl.dropboxusercontent.com/u/7203428/SO/lowerframe_sketch.png)到我的Dropbox文件夹,显示我想要达到的效果 – albert 2014-11-23 17:50:35

+0

@albert:给予你想要的宽度具有明确的宽度,并且对要增长或缩小的列使用非零权重。这里没有魔法,这都是非常确定的。如果您希望可变宽度的_between_小部件,创建一个没有任何小部件的列,并为该列赋予权重。 – 2014-11-23 17:53:12