tkinter-place佈局詳解

前文介紹了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: [email protected]
# @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的佈局就介紹到這裏,如果大家發現有好玩的或不太會用的屬性,可以評論下方留言,一起交流學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章