轉載
原文地址:https://blog.csdn.net/shmilycoder/article/details/80817789

- 原文博客地址: Tkinter之組件布局和事件綁定
- 前面的一些文章介紹了
Tkinter模塊和大部分組建的使用 - 這里主要介紹數據的操作和組件布局等
- GitHub代碼示例目地址
一. 數據顯示
在tkinter中的數據展示方式有兩種表格數據和樹狀數據, 但是都用到同一個組件Treeview, 下面介紹組建的使用
1. 表格數據
- 表格數據, 顧名思義就是用表格形式展示數據
- 要使用
Treeview首先要引用tkinter中的ttk模塊
from tkinter import ttk # 此處省略window的相關代碼 # 創建表格 tree = ttk.Treeview(window) tree.pack() # 定義列title(接受一個元組) tree["columns"] = ('name', 'sex', 'age', 'height', 'weight') # 設置列寬度 tree.column('name', width=100) tree.column('sex', width=50) tree.column('age', width=50) tree.column('height', width=80) tree.column('weight', width=80) # 設置表頭(列名) tree.heading('name', text='姓名') tree.heading('sex', text='性別') tree.heading('age', text='年齡') tree.heading('height', text='身高(CM)') tree.heading('weight', text='體重(KG)') # 添加數據 tree.insert('', 0, text='line1', values=('Titan', 'M', 20, 180, 80)) tree.insert('', 1, text='line2', values=('Jun', 'M', 19, 170, 65)) tree.insert('', 2, text='line3', values=('Coder', 'M', 20, 170, 70)) tree.insert('', 3, text='line4', values=('Che', 'W', 18, 165, 45)) # 上面第一個參數為第一層級, 這里目前用不到, 后面樹狀結構中會用到
效果圖如下

2. 樹狀數據
樹狀數據這里指的是,類似文件夾的層級目錄一樣
# 創建表格
tree = ttk.Treeview(window)
tree.pack()
# 添加一級樹枝
treeA1 = tree.insert('', 0, '浙', text='浙江', values=('A1')) treeA2 = tree.insert('', 1, '魯', text='山東', values=('A2')) treeA3 = tree.insert('', 2, '蘇', text='江蘇', values=('A3')) # 添加二級樹枝 treeA1_1 = tree.insert(treeA1, 0, 'H', text='杭州', values=('A1_1')) treeA1_2 = tree.insert(treeA1, 1, 'Z', text='舟山', values=('A1_2')) treeA1_3 = tree.insert(treeA1, 2, 'J', text='嘉興', values=('A1_3')) treeA2_1 = tree.insert(treeA2, 0, 'N', text='濟南', values=('A2_1')) treeA2_2 = tree.insert(treeA2, 1, 'L', text='臨沂', values=('A2_2')) treeA2_3 = tree.insert(treeA2, 2, 'Q', text='青島', values=('A2_3')) treeA2_4 = tree.insert(treeA2, 3, 'Y', text='煙台', values=('A2_4')) # 三級樹枝 treeA1_1_1 = tree.insert(treeA1_1, 0, 'G', text='江干', values=('A1_1_1')) treeA1_1_1 = tree.insert(treeA1_1, 1, 'X', text='蕭山', values=('A1_1_2'))
注意事項
-insert: 參數介紹
- 參數1: 上一層級的目錄
- 參數2: 當前數據在當前層級的中的索引值
- 參數3: 當前數據的標識, 所有層及數據的該標識不能相同, 否則報錯
- 參數4: 顯示的數據
- 注: 所有數據的參數3(標識)不能相同
效果圖如下

二. 布局方式
- 所謂布局,就是指控制窗體容器中各個控件(組件)的位置關系。
- 在
tkinter中目前存在的布局方式有三種: 絕對布局(place), 相對布局(pack)和表格布局(grid)
1. 絕對布局
- 絕對布局: 窗口的變化對位置沒有影響
- 這里先介紹
place布局涉及到的相關屬性和函數
1-1. 屬性介紹
| 屬性名 | 屬性簡析 | 取值 | 取值說明 |
|---|---|---|---|
anchor |
錨點, 當可用空間大於所需求的尺寸時,決定組件被放置於容器的何處 | N、E、S、W、NW、NE、SW、SE、CENTER(默認值) |
表示八個方向以及中心 |
x、y |
組件左上角的x、y坐標 | 整數,默認值0 | 絕對位置坐標,單位像素 |
relx/rely |
組件相對於父容器的x、y坐標 | 0~1之間浮點數 | 相對位置,0.0表示左邊緣(或上邊緣),1.0表示右邊緣(或下邊緣) |
width/height |
組件的寬度、高度 | 非負整數 | 單位像素 |
relwidth、relheight |
組件相對於父容器的寬度、高度 | 0~1之間浮點數 | 與relx(rely)取值相似 |
bordermode |
如果設置為INSIDE,組件內部的大小和位置是相對的,不包括邊框;如果是OUTSIDE,組件的外部大小是相對的,包括邊框 |
INSIDE(默認)、OUTSIDE |
可以使用常量INSIDE、OUTSIDE,也可以使用字符串形式inside、outside |
# 創建四個label
label1 = Label(window, text='11111', bg='red') label2 = Label(window, text='22222', bg='yellow') label3 = Label(window, text='33333', bg='blue') label4 = Label(window, text='44444', bg='orange') # 絕對布局 label1.place(x=10, y=10, width=200) label2.place(x=30, y=30) label3.place(x=60, y=61) label4.place(x=91, y=91, width=200, height=50)
如下圖組件位置固定

1-2. 相關函數
place類提供了下列函數(使用組件實例對象調用)
place_slaves(): 以列表方式返回本組件的所有子組件對象place_configure(option=value): 給place布局管理器設置屬性,使用屬性option=value方式設置propagate(boolean): 設置為True表示父組件的幾何大小由子組件決定(默認值),反之則無關place_info(): 返回place提供的選項所對應得值grid_forget():Unpack組件,將組件隱藏並且忽略原有設置,對象依舊存在,可以用pack(option, …),將其顯示location(x, y):x/y為以像素為單位的點,函數返回此點是否在單元格中,在哪個單元格中。返回單元格行列坐標,(-1, -1)表示不在其中size(): 返回組件所包含的單元格,揭示組件大小
2. 相對布局
2-1. 屬性介紹
- 相對布局: 組件位置或大小的變化會隨着窗口的變化而變化
- 這里先介紹
pack布局涉及到的相關屬性和函數
| 屬性名 | 屬性簡析 | 取值 | 取值說明 |
|---|---|---|---|
fill |
設置組件是否向水平或垂直方向填充 | X、Y、BOTH和NONE |
fill=X(水平方向填充),BOTH(水平和垂直),NONE不填充 |
expand |
設置組件是否展開 | YES、NO(1、0) | expand=YES |
side |
設置組件的對齊方式 | LEFT、TOP、RIGHT、BOTTOM |
值為左、上、右、下 |
ipadx/ipady |
設置x方向(或者y方向)內部間隙(子組件之間的間隔) | 可設置數值,默認是0 | 非負整數,單位為像素 |
padx/pady |
設置x方向(或者y方向)外部間隙(與之並列的組件之間的間隔) | 可設置數值,默認是0 | 非負整數,單位為像素 |
anchor |
錨選項,當可用空間大於所需求的尺寸時,決定組件被放置於容器的何處 | N、E、S、W、NW、NE、SW、SE、CENTER(默認值為CENTER) | 表示八個方向以及中心 |
需要注意
expand: 設置組件是否展開,當值為YES時,side選項無效。組件顯示在父容器中心位置;若fill選項為BOTH,則填充父組件的剩余空間。默認為不展開
# 創建四個label
label1 = Label(window, text='11111', bg='red') label2 = Label(window, text='22222', bg='yellow') label3 = Label(window, text='33333', bg='blue') label4 = Label(window, text='44444', bg='orange') # 布局 label1.pack(side=LEFT, fill=Y) label2.pack(side=RIGHT, fill=Y) label3.pack(side=TOP, fill=X) label4.pack(side=BOTTOM, fill=X)
效果如圖

2-2. 函數介紹
pack類提供了下列函數(使用組件實例對象調用)
- pack_slaves(): 以列表方式返回本組件的所有子組件對象
- pack_configure(option=value): 給pack布局管理器設置屬性,使用屬性option=value方式設置
- propagate(boolean): 設置為 True 表示父組件的幾何大小由子組件決定(默認值),反之則無關。
- ack_info(): 返回pack提供的選項所對應得值。
- pack_forget(): Unpack組件,將組件隱藏並且忽略原有設置,對象依舊存在,可以用pack(option, …),將其顯示。
- location(x, y): x, y為以像素為單位的點,函數返回此點是否在單元格中,在哪個單元格中。返回單元格行列坐標,(-1, -1)表示不在其中
- size(): 返回組件所包含的單元格,揭示組件大小
3. 表格布局
grid布局又被稱作網格布局,是最被推薦使用的布局。- 程序大多數都是矩形的界面,我們可以很容易把它划分為一個幾行幾列的網格,然后根據行號和列號,將組件放置於網格之中
- 使用
grid布局時,需要在里面指定兩個參數,分別用row表示行,column表示列 - 需要注意的是
row和column的序號都從0開始
3-1. 屬性介紹
| 屬性名 | 屬性簡析 | 取值 | 取值說明 |
|---|---|---|---|
row/column |
row為行號,column為列號,設置將組件放置於第幾行第幾列 |
取值為行、列的序號,不是行數與列數 | row和column 的序號都從0 開始 |
sticky |
設置組件在網格中的對齊方式 | N、E、S、W、NW、NE、SW、SE、CENTER |
類似於pack布局中的錨選項 |
rowspan |
組件所跨越的行數 | 跨越的行數 | 取值為跨越占用的行數,而不是序號 |
columnspan |
組件所跨越的列數 | 跨越的列數 | 取值為跨越占用的列數,而不是序號 |
ipadx/ipady |
設置x方向(或者y方向)內部間隙(子組件之間的間隔) | 可設置數值,默認是0 | 非負整數,單位為像素 |
padx/pady |
設置x方向(或者y方向)外部間隙(與之並列的組件之間的間隔) | 可設置數值,默認是0 | 非負整數,單位為像素 |
# 創建四個label
label1 = Label(window, text='11111', bg='red') label2 = Label(window, text='22222', bg='yellow') label3 = Label(window, text='33333', bg='blue') label4 = Label(window, text='44444', bg='orange') # 布局 label1.grid(row=0, column=0) label2.grid(row=0, column=1) label3.grid(row=1, column=0) label4.grid(row=1, column=1)
效果如圖

3-2. 函數介紹
grid類提供了下列函數(使用組件實例對象調用):
| 函數名 | 描述 |
|---|---|
grid_slaves() |
以列表方式返回本組件的所有子組件對象。 |
grid_configure(option=value) |
給grid布局管理器設置屬性 |
grid_propagate(boolean) |
設置為True表示父組件的幾何大小由子組件決定(默認值),反之則無關。 |
grid_info() |
返回grid提供的選項所對應得值。 |
grid_forget() |
將組件隱藏並且忽略原有設置,對象依舊存在 |
grid_location(x, y) |
x/y為以像素為單位的點,函數返回此點是否在單元格中 |
size() |
返回組件所包含的單元格,揭示組件大小 |
三. 鼠標和鍵盤事件
- 一個
Tkinter應用生命周期中的大部分時間都處在一個消息循環中 - 它等待事件的發生: 事件可能是按鍵按下, 鼠標點擊, 鼠標移動等.
Tkinter提供了用以處理相關事件的機制, 處理函數可以被綁定給各個控件的各種事件- 如果相關事件發生,
handler函數會被觸發, 事件對象event會傳遞給handler函數
button.bind(event, handler)
- 1
1. 鼠標點擊事件
def buttonAction(event): print(event.x, event.y) button = Button(window, text='這是一個按鈕') button.bind('<Button-4>', buttonAction) button.pack()
其中event的事件類型和描述如下
| Event | Description |
|---|---|
<Button-1> |
鼠標左鍵 |
<Button-3> |
鼠標右鍵 |
<Button-2> |
鼠標中鍵 |
<Button-4> |
鼠標向上滾動 |
<Button-5> |
鼠標向下滾動 |
<Double-Button-1> |
鼠標左鍵雙擊 |
<Double-Button-3> |
鼠標右鍵雙擊 |
<Double-Button-2> |
鼠標中鍵雙擊 |
<Triple-Button-1> |
鼠標左鍵三擊 |
<Triple-Button-3> |
鼠標右鍵三擊 |
<Triple-Button-2> |
鼠標中鍵三擊 |
2. 鼠標在某個按鍵被按下后的移動事件
label = Label(window, text='https://www.titanjun.top', bg='orange') label.place(x=100, y=50, height=30) def labelAction(event): print(event.x, event.y) label.bind('<B1-Motion>', labelAction)
其中event的事件類型和描述如下
| Event | Description |
|---|---|
<B1-Motion> |
左鍵移動 |
<B3-Motion> |
右鍵移動 |
<B2-Motion> |
中鍵移動 |
3. 按鈕點擊釋放事件
label = Label(window, text='https://www.titanjun.top', bg='orange') label.place(x=100, y=50, height=30) def labelAction(event): print(event.x, event.y) label.bind('<ButtonRelease-1>', labelAction)
其中event的事件類型和描述如下
| Event | Description |
|---|---|
<ButtonRelease-1> |
釋放鼠標左鍵 |
<ButtonRelease-3> |
釋放鼠標右鍵 |
<ButtonRelease-2> |
釋放鼠標中鍵 |
需要注意的是
- 以上鼠標操作中, 蘋果鼠標沒有中鍵這一說, 所以在蘋果鼠標操作中
- 正常鼠標的中鍵操作(例如<Button-2>等-2操作), 響應蘋果鼠標的右鍵操作
- 正常鼠標的右鍵操作(例如<Button-3>等-3操作), 在蘋果鼠標中無響應
4. 鼠標進入/離開控件事件
# 按鈕點擊釋放事件 label3 = Label(window, text='加油: https://www.titanjun.top', bg='yellow') label3.place(x=100, y=150, height=30) def labelAction(event): print(event.x, event.y) label3.bind('<Leave>', labelAction)
其中event的事件類型和描述如下
| Event | Description |
|---|---|
<Enter> |
鼠標光標進入控件時觸發 |
<Leave> |
鼠標光標離開控件時觸發 |
5. 鍵盤響應事件
# 響應所有的按鍵 label = Label(window, text='https://www.titanjun.top', bg='orange') # 設置焦點 label.focus_set() label.place(x=100, y=50, height=30) def labelAction(event): print(event.char, event.keycode) label.bind('<Key>', labelAction)
其他按鍵操作
| Event | Description |
|---|---|
<Key> |
響應所有的按鍵(按下) |
<KeyRelease> |
響應所有的按鍵(松開) |
<FocusIn> |
控件或控件的子空間獲得鍵盤焦點. |
<FocusOut> |
控件丟失鍵盤焦點 (焦點移動到另一個控件). |
6. 指定按鍵操作
| Event | Description |
|---|---|
<Return>/<Enter> |
只有回車鍵響應 |
<Escape> |
esc鍵 |
<space> |
空格鍵 |
<Tab> |
Tab鍵 |
<Up>/<Down>/<Left>/<Right> |
上下左右鍵 |
<Shitf_L>/<Shift_R> |
左右Shift鍵(類似有左右兩個鍵的, 添加_L/_R區分) |
<BackSpace> |
退格 |
<a>/<b> |
指定的小寫字母鍵 |
<A>/<Z> |
指定的大寫字母鍵 |
<Control-Alt-a> |
組合鍵(可識別任意組合鍵) |
需要注意的是: 識別組合鍵時, 一般是按下組合鍵的最后一個鍵才會觸發操作
7. event事件的相應參數
| 時間屬性 | 描述 |
|---|---|
char |
從鍵盤輸入的和按鍵事件的相關字符 |
keycode |
從按鍵輸入的和按鍵事件的鍵代碼(ASCII碼) |
keysym |
從按鍵輸入的和按鍵事件的鍵符號(即字符) |
num |
按鍵數字(1, 2, 3)表明按下的是哪個鼠標鍵 |
widget |
觸發這個事件的小構件對象 |
x和y |
當前鼠標在小構件中以像素為單位的位置 |
x_root和y_root |
當前鼠標相對於屏幕左上角的以像素為單位的位置 |
