前文介绍了tkinter中的grid布局,相信对tkinter的布局套路有了进一步的了解。本文将介绍另一种布局类place。

同样,展示布局类与控件类的类间关系:

在这里插入图片描述

place

place(cnf={}, **kw)

place和其他两种布局方式相比,更加"自由"但是需要做的事情也多。布局一般就是设置子控件相对于父控件的 起始位置、宽和高。在pack、grid的布局方式中,起始位置、宽和高都会给默认配置,所以使用起来会更"简",代价就是"控制权"减少。所以place虽然"繁",但完全自主控制。三种布局方式,没有哪种最好,哪种不好,看实际需要求选着合适的即可。

下面,我们先过一遍place的常见属性,展示其含义及用法。

按照之前两篇文章的思路,place()先不传参,直接调用。看看会是什么效果呢?

from tkinter import (Tk, Button)
from tkinter.constants import RIGHT, LEFT, X, Y, BOTH

main_win = Tk()
main_win.title('渔道的grid布局')
width = 300 
height = 300 
main_win.geometry(f'{width}x{height}')
# print(main_win.keys())

apple_color = 'Crimson'
banana_color = 'Yellow'
orange_color = 'Orange'
grape_color = 'Purple'

fruit = {'apple':'Crimson', 'banana':'Yellow', 'orange':'Orange', 'grape':'Purple'}

# 默认显示效果
i = 0
for k,v in fruit.items():
    bt = Button(main_win, text=k, fg='black', bg=v)
    bt.place()
    print(bt.place_info())
    i += 1
    
main_win.mainloop()

和我预想的结果不一样哦!没有按钮显示出来!而且,print函数打印的place_info信息都为空字典。这样的结果也说明了place的"完全自主控制",至少需要指定起始坐标,否则place对象不知道将button放在哪儿。
在这里插入图片描述

x

指定 控件的在x轴的坐标值

y

指定 控件在y轴的坐标值

那么,既然要让place知道将button放在哪儿,我尝试一下,将place()指定x=0,看看是什么效果呢?

for k,v in fruit.items():
    bt = Button(main_win, text=k, fg='black', bg=v)
    bt.place(x=0)
    print(bt.place_info())

print的打印信息如下:
在这里插入图片描述

从下面的效果可以发现,四个按钮是显示出来了,但是重叠在一起。原因就是起始坐标都是(0,0),所以当然会覆盖,grape button是最后显示,所以它在最上面。
在这里插入图片描述

从上面的结果,我们会自然的想到,调整(x,y)改变button的起始位置,应该就能将4个按钮正常的显示出来。下面,我们试试

i = 0
for k,v in fruit.items():
    bt = Button(main_win, text=k, fg='black', bg=v)
    bt.place(x=0, y=i*30)
    print(bt.place_info())
    i += 1

先看看print的打印信息:
在这里插入图片描述

通过将y坐标分别设置为0,30,60,90,我们可以看到,4个按钮被正常的显示出来,没有并覆盖。
在这里插入图片描述

ok,以上就是属性x,y的用法。控件要想显示在哪儿,就可以通过指定(x,y),即绝对坐标,来设置控件的绝对位置。

从上面的示例中我们还看到了 relx, rely, width, height,relwidth, relheight,anchor, bordermode这些属性,下面我们来一一解读这些属性。

relx

从relx的命名上,可猜测出relx表示相对坐标(PS:relative),那既然是"相对的",显然是相对父控件咯。这都是凭借自己的经验的猜测,到底是不是这样呢?relx的值应该怎么给呢?

通过tkinter的源码,我们看到对relx的说明:

relx=amount - locate anchor of this widget between 0.0 and 1.0 relative to width of master (1.0 is right edge)

从上面的注释我们可以发现,relx的作用确实是指定相对坐标,relx的取值为0~1的小数。如果relx=0,表示子控件的x方向的起始位置在父控件的最左边;如果rely=1,表示子控件的y方向的起始位置在父控件的最右边。

rely

显然,rely的作用和relx相同,只不过是表示y方向的起始位置。

好了,既然我们知道relx和rely的作用,到底代码运行的实际效果是不是和我们想象的一样呢?我们试验一下,将relx=0.5, rely=0.5,看看子控件是否将父控件的中心位置作为起始位置。

for k,v in fruit.items():
    bt = Button(main_win, text=k, fg='black', bg=v)
    bt.place(relx=0.5, rely=0.5)
    print(bt.place_info())

print的打印信息:
在这里插入图片描述

从打印信息可以看出,四个按钮的relx和rely都为0.5,那么4个按钮都是将主窗口的中心位置作为起始位置,这样4个按钮应该会重叠。下面的效果显示也印证了。要想将4个按钮都显示出来而不重叠,类似x,y,设置适当的relx和rely值,使按钮不重叠即可。非常简单,这里就不再用代码演示了,可以自己试试修改relx和rely的值,然后看看效果。
在这里插入图片描述

width

指定 控件的宽度

height

指定 控件的高度

这两个属性的作用显而易见,我们设置相应的值来看看实际运行后的效果,是否与自己预想的一致呢?

i = 0
w = 60
h = 30
for k,v in fruit.items():
    bt = Button(main_win, text=k, fg='black', bg=v)
    bt.place(x=i*w, y=i*h, width=w, height=h)
    print(bt.place_info())
    i += 1

print的打印信息如下:
在这里插入图片描述

从打印信息可以看出,控件的宽和高是我们设置的值,起始位置坐标也和设置的值一致。
在这里插入图片描述

anchor

锚点的值可设置为:n, ne, e, se, s, sw, w, nw, or center。place的anchor属性非常有意思,下面详细介绍一下。

# -*- coding:utf-8 -*-
# @Author: Frank
# @Email: junfu0903@aliyun.com
# @Date: 2020-07-03 22:54:34
# @LastEditTime: 2020-07-03 22:56:48
# @Description: 
# @FilePath: \python\pb_basic\test_tkinter\15place_anchor.py
from tkinter import (Tk, Button, Canvas)
from tkinter.constants import RIGHT, LEFT, X, Y, BOTH

main_win = Tk()
main_win.title('渔道的place布局')
width = 300 
height = 300 
main_win.geometry(f'{width}x{height}')

cav = Canvas(main_win, bg='blue', width=300, height=300)
cav.pack()
cav.create_line(0,150,300,150,fill='red')
cav.create_line(150,0,150,300,fill='red')

# anchor n, ne, e, se, s, sw, w, nw, or center
x=150
y=150
bt = Button(cav, text='apple', fg='black', bg='red')
bt.place(x=x, y=y, anchor='e')
print(bt.place_info())

bt = Button(cav, text='banana', fg='black', bg='yellow')
bt.place(x=x, y=y, anchor='w')
print(bt.place_info())

bt = Button(cav, text='orange', fg='black', bg='orange')
bt.place(x=x, y=y, anchor='n')
print(bt.place_info())

bt = Button(main_win, text='grape', fg='black', bg='purple')
bt.place(x=x, y=y, anchor='s')
print(bt.place_info())

bt = Button(main_win, text='pear', fg='black', bg='white')
bt.place(x=x, y=y, anchor='center')
print(bt.place_info())

main_win.mainloop()

这段示例代码就是用来说明 place的anchor属性。

第19,20行代码,画了两条交叉的直线,交点即为主窗口的中心点(150,150)。作用是为了方便演示。

第25,29,33,37,41行,创建了5个按钮,分别设置不同的颜色。

重点来了!重点来了!重点来了!

第26行,将apple按钮的起始点坐标设为(150,150),同时anchor设置为’e’; 意思就是锚点在东边,也就是右边

锚点是指什么点?锚点即是x,y属性设置的坐标点。

锚点相对于谁 在东边?本例就是 锚点相对于按钮在东边(左边)。

所以 相对的,按钮放置在锚点的左边;

第30行,将banana按钮的起始点坐标设为(150,150),同时anchor设置为’w’;意思就是锚点在西边,也就是左边

所以 相对的,按钮放置在锚点的右边;

第33行,将orange按钮的起始点坐标设为(150,150),同时anchor设置为’n’;意思就是锚点在北边,也就是上边

所以 相对的,按钮放置在锚点的下边;

第37行,将grape按钮的起始点坐标设为(150,150),同时anchor设置为’s’;意思就是锚点在南边,也就是下边

所以 相对的,按钮放置在锚点的上边;

第41行,将pear按钮的起始点坐标设为(150,150),同时anchor设置为’center’;意思就是锚点在中间

所以 按钮的中心点为(150,150);

下面,我们来看看实际代码运行后的效果与我们分析的是否一致。
在这里插入图片描述

从上图中可以看到,坐标点(150,150)是主窗口的中心点。apple按钮显示在中心点的左边;banana按钮显示在中心点的右边;grape按钮显示在中心点的上边;orange按钮显示在中心点的下边;pear按钮的中心和主窗口的中心点重合。实际显示效果和我们分析的情况完全一致!完美!

综上所述,place的anchor属性的作用即是 设置控件锚点的位置。大家理解了吗?

小结:通过三篇博文对pack,grid,place的介绍,相信大家能感觉到这三种布局类的差异。pack和grid相对来说,需要控制的细节要少一些,主要由对象来完成一些默认的布局规则,同时也就降低了programmer的控制能力;place就完全由programmer自己完成布局的控制。这三种方式没有哪一种好哪一种不好,主要看使用场景,谁能更好的满足场景需求,就用谁。

好了,关于tkinter的布局就介绍到这里,如果大家发现有好玩的或不太会用的属性,可以评论下方留言,一起交流学习。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐