使用Tk Grid几何管理器进行GUI布局

13 投票
1 回答
29271 浏览
提问于 2025-04-17 03:00

我正在用Python做一个小应用程序,想尝试一下用Tkinter做点图形界面(GUI)编程。这是我目前创建的界面:

使用Tkinter的GUI布局

关于应用程序的疑问:

我该如何确保截图中的三个LabelFrame - A、B和C - 宽度相同?(或者说,宽度要和三个中最宽的那个相等?比如在截图中,A是最宽的,我希望B和C也能和A一样宽,直到D那条线为止。)

(不需要动态计算,只要我在编写代码时第一次就能确保它们的宽度相同就可以了。运行时不需要改变。)

关于Tk Grid几何管理器的疑问:

  1. 使用框架时,网格(行,列)是仅针对框架的大小,还是根据整个窗口的大小来计算的?

  2. 网格中列的大小是如何确定的?

  3. 我还没有完全理解网格中的“权重”是干什么的。什么时候应该使用它?

Python GUI代码:

import Tkinter

if __name__ == '__main__':
    form = Tkinter.Tk()

    getFld = Tkinter.IntVar()

    form.wm_title('File Parser')

    stepOne = Tkinter.LabelFrame(form, text=" 1. Enter File Details: ")
    stepOne.grid(row=0, columnspan=7, sticky='W', \
                 padx=5, pady=5, ipadx=5, ipady=5)

    helpLf = Tkinter.LabelFrame(form, text=" Quick Help ")
    helpLf.grid(row=0, column=9, columnspan=2, rowspan=8, \
                sticky='NS', padx=5, pady=5)
    helpLbl = Tkinter.Label(helpLf, text="Help will come - ask for it.")
    helpLbl.grid(row=0)

    stepTwo = Tkinter.LabelFrame(form, text=" 2. Enter Table Details: ")
    stepTwo.grid(row=2, columnspan=7, sticky='W', \
                 padx=5, pady=5, ipadx=5, ipady=5)

    stepThree = Tkinter.LabelFrame(form, text=" 3. Configure: ")
    stepThree.grid(row=3, columnspan=7, sticky='W', \
                   padx=5, pady=5, ipadx=5, ipady=5)

    inFileLbl = Tkinter.Label(stepOne, text="Select the File:")
    inFileLbl.grid(row=0, column=0, sticky='E', padx=5, pady=2)

    inFileTxt = Tkinter.Entry(stepOne)
    inFileTxt.grid(row=0, column=1, columnspan=7, sticky="WE", pady=3)

    inFileBtn = Tkinter.Button(stepOne, text="Browse ...")
    inFileBtn.grid(row=0, column=8, sticky='W', padx=5, pady=2)

    outFileLbl = Tkinter.Label(stepOne, text="Save File to:")
    outFileLbl.grid(row=1, column=0, sticky='E', padx=5, pady=2)

    outFileTxt = Tkinter.Entry(stepOne)
    outFileTxt.grid(row=1, column=1, columnspan=7, sticky="WE", pady=2)

    outFileBtn = Tkinter.Button(stepOne, text="Browse ...")
    outFileBtn.grid(row=1, column=8, sticky='W', padx=5, pady=2)

    inEncLbl = Tkinter.Label(stepOne, text="Input File Encoding:")
    inEncLbl.grid(row=2, column=0, sticky='E', padx=5, pady=2)

    inEncTxt = Tkinter.Entry(stepOne)
    inEncTxt.grid(row=2, column=1, sticky='E', pady=2)

    outEncLbl = Tkinter.Label(stepOne, text="Output File Encoding:")
    outEncLbl.grid(row=2, column=5, padx=5, pady=2)

    outEncTxt = Tkinter.Entry(stepOne)
    outEncTxt.grid(row=2, column=7, pady=2)

    outTblLbl = Tkinter.Label(stepTwo, \
          text="Enter the name of the table to be used in the statements:")
    outTblLbl.grid(row=3, column=0, sticky='W', padx=5, pady=2)

    outTblTxt = Tkinter.Entry(stepTwo)
    outTblTxt.grid(row=3, column=1, columnspan=3, pady=2, sticky='WE')

    fldLbl = Tkinter.Label(stepTwo, \
                           text="Enter the field (column) names of the table:")
    fldLbl.grid(row=4, column=0, padx=5, pady=2, sticky='W')

    getFldChk = Tkinter.Checkbutton(stepTwo, \
                           text="Get fields automatically from input file",\
                           onvalue=1, offvalue=0)
    getFldChk.grid(row=4, column=1, columnspan=3, pady=2, sticky='WE')

    fldRowTxt = Tkinter.Entry(stepTwo)
    fldRowTxt.grid(row=5, columnspan=5, padx=5, pady=2, sticky='WE')

    transChk = Tkinter.Checkbutton(stepThree, \
               text="Enable Transaction", onvalue=1, offvalue=0)
    transChk.grid(row=6, sticky='W', padx=5, pady=2)

    transRwLbl = Tkinter.Label(stepThree, \
                 text=" => Specify number of rows per transaction:")
    transRwLbl.grid(row=6, column=2, columnspan=2, \
                    sticky='W', padx=5, pady=2)

    transRwTxt = Tkinter.Entry(stepThree)
    transRwTxt.grid(row=6, column=4, sticky='WE')

    form.mainloop()

(注意:适用于Python 2.4.3)

1 个回答

14

如果你在三个LabelFrame上使用相同的列跨度,并且都设置了sticky='WE',那么它们的宽度应该是一样的。比如,你想要使用

stepTwo = Tkinter.LabelFrame(form, text=" 2. Enter Table Details: ")
stepTwo.grid(row=2, columnspan=7, sticky='WE', \
             padx=5, pady=5, ipadx=5, ipady=5)

问题

1) 当你使用框架时,网格(行,列)是仅仅针对框架的大小,还是根据整个窗口的大小来计算的?

这里有个相互依赖的关系。整个窗口的理想大小会依赖于里面小部件的理想大小和布局,但小部件的实际大小又会依赖于整个窗口的实际大小和布局。布局是从小部件开始,到根窗口来确定理想大小,然后再回到根窗口时,理想大小就会被当作实际大小(除非有其他设置)。接着,布局会再往下分配实际大小。

2) 网格中一列的大小是怎么确定的?

一列的理想大小是根据该行中所有项目的最小理想宽度来决定的。而这一列的实际大小则是理想大小加上父级小部件额外空间的一部分。

3) 我还没有完全理解网格中的“权重”是干什么用的。什么时候应该使用它?

权重决定了我刚才提到的额外空间的百分比。分配给这一列的额外空间是通过列的权重除以总权重来计算的。

撰写回答