Python grid布局的简介与细节进阶 (3)
前两节我们:
- 介绍了tkinter库(Python标准GUI库)grid布局的基本概念
- 通过一个样例程序,讲解了grid布局与frame部件的配合使用技巧
1. Frame的宽高设置以及grid_propagate()方法
1.1 Frame的宽高设置
假如说,我们想让主界面稍微大一些,就算285像素宽210像素高吧。看起来,实现这一点只需要修改一下frm_root的属性即可:
|
|
但程序执行起来的结果和没有设置前毫无变化。主窗口的长宽与我们指定的值并不一致。这是为什么呢?
1.2 grid_propagate()设置
这是因为frame等容器类部件有一个grid_propagate的设置,其缺省设置为1(enabled):
- 当该设置enabled时(widget.grid_propagate(1)):frame的大小将随其中容纳的所有部件的大小而变化,即frame的大小保证刚好能装下所有部件,frame部件本身的长宽设置不再起作用;
- 当该设置disabled时(widget.grid_propagate(0)): frame的大小遵从其自身的长宽设置,不再考虑内部容纳部件的大小。
因此,我们只需disable掉frm_root的grid_propagate设置即可:
|
|
通过运行结果可见,新的主界面确实比原来大了:
但现在所有部件还都紧紧地挤在一起,堆在主界面的右上角。看来通过修改frame大小,并不能很好地改善我们的布局。
下面,我们通过grid()方法的pad(外部间距)与ipad(内部间距)设置,以及部件的pad(内部间距)属性来进一步调节各个部件的位置。
2. grid()方法的pad/ipad设置与部件的pad属性
2.1 pad与ipad简介
无论是grid()方法的pad/ipad设置,还是部件的pad属性,都是用来调整部件间距的。
这里我们借用HTML/CSS中的margin(外部间距)/padding(内部间距)来理解一下:
不用过多解释,这幅图已经很好地解释了什么是margin(外部间距),什么是padding(内部间距)。
上图摘自Jon Duckett所著HTML & CSS - Design and Build Websites的第13章 Boxes。顺便强力推荐一波,这本书不仅将HTML/CSS相关概念讲得非常清晰有条理,而且其排版更是干净、漂亮,宛如一尊精致的工艺品(下面是两段样张):
2.2 grid()方法的pad/ipad设置
grid()方法中的pad分为padx、pady,分别用以设置控件外部的横向间距与纵向间距,对应上述HTML/CSS中的margin;ipad同样分为ipadx、ipady,用以设置控件内部的横向间距与纵向间距,对应上述HTML/CSS中的padding。
使用方法为:
如果左右边距或上下边距需要设置为不一致的值,我们可以将一个包含两个值的tuple传给相关属性,如:
2.3 部件的pad属性
部件的pad属性同样分为padx、pady,分别用以设置控件内部的横向间距与纵向间距,对应HTML/CSS中的padding。
使用方法为(以Label为例):
注意:
- 部件的pad属性不支持tuple赋值,即不支持左右边距或上下边距不一致
- 部件没有ipad属性
2.4 样例程序,以及grid()方法pad/ipad设置与部件pad属性的配合使用
我们用最简单的界面(主界面上只有一个Label)来演示相关效果。同时为了看清楚内外间距,我们特意把Label的border描出来了。
2.4.1 原始程序
|
|
运行结果:
2.4.2 设置Label的内边距
我们只需要改创建lbl_tags对象的语句:
运行结果:
2.4.3 设置Label的外边距
由于部件自身没有ipad属性,因此我们需要设置其grid()方法中的pad设置:
运行结果:
2.4.3 内外边距配合使用
一般来说,我们:
- 通过部件本身的pad属性,设置内部边距;
- 通过部件grid()方法的pad设置,设置其外部边距
理论上,部件的外部边距也可以被视为其所在Frame的内部边距,但由于grid()方法的ipad设置在某些场景下会出现问题,所以并不推荐这么使用。
举一个例子,我们按照这个思路改写一下程序:
|
|
其运行结果就比较诡异了:
这里tkinter似乎知道要去设置frame的内部边距(即label的外部边距),但是却阴差阳错设置错了。所以,一般来说,没有特殊需要,我们不使用grid()方法的ipad设置。