文章目錄
事件綁定的基本簡介
其實GUI程序是一種事件導向
的應用程序設計,事件的來源可能是用戶單擊鼠標、鍵盤輸入或是Widget 狀態改變。tkinter提供一些機制讓我們可以針對這些事件做更進一步的處理,這些處理的方式稱爲事件處理程序
Widget 的 command 參數
例子
:複習
import tkinter
def show():
label.config(text="Click")
def oneVar():
if varOne.get():
label.config(text="One!!!")
else:
label.config(text="One")
def twoVar():
if varTwo.get():
label.config(text="Two!!!")
else:
label.config(text="Two")
root = tkinter.Tk()
root.geometry("300x200")
btu = tkinter.Button(root, text="Click", command=show)
btu.pack(anchor=tkinter.W)
varOne = tkinter.BooleanVar()
cbnOne = tkinter.Checkbutton(root, text="One", variable=varOne, command=oneVar)
cbnOne.pack(anchor=tkinter.W)
varTwo = tkinter.BooleanVar()
cbnTwo = tkinter.Checkbutton(root, text="Two", variable=varTwo, command=twoVar)
cbnTwo.pack(anchor=tkinter.W)
label = tkinter.Label(root, bg="lightgreen", fg="red", height=2, width=12, font="Times 16 bold")
label.pack()
root.mainloop()
運行結果:
我們通過command=show
,來設計show函數,這個show函數就是事件處理程序
事件綁定
語法格式如下
widget.bind(event, handler)
參數:
- widget:事件的來源,可以是root窗口對象,或是任意的Widget控件,例如,功能按鈕,選項按鈕,複選框等等
- 第一個參數:
evevt
,事件的參數,下面具體說明 - 第二個參數:
handler
,事件處理程序,也就是根據event來觸發的函數
下面我們來看具體參數
鼠標相關的事件參數
鼠標事件 | 說明 |
---|---|
<Button-1> | 鼠標左鍵單擊 |
<Button-2> | 鼠標中鍵單擊 |
<Button-3> | 鼠標右鍵單擊 |
<Button-4> | 鼠標滑輪向上滾動(Linux) |
<Button-5> | 鼠標滑輪向下滾動(Linux) |
<B1-Motion> | 鼠標左鍵拖動 |
<B2-Motion> | 鼠標中鍵拖動 |
<B3-Motion> | 鼠標右鍵拖動 |
<ButtonRelease-1> | 鼠標左鍵釋放 |
<ButtonRelease-2> | 鼠標中鍵釋放 |
<ButtonRelease-3> | 鼠標右鍵釋放 |
<Double-Button-1> | 鼠標左鍵雙擊 |
<Double-Button-2> | 鼠標中鍵雙擊 |
<Double-Button-3> | 鼠標右鍵雙擊 |
<Enter> | 鼠標指針進入控件 |
<Leave> | 鼠標指針離開控件 |
上述的參數,執行後鼠標光標相對控件的位置會被存入事件對象的x和y變量中,所以這就是爲什麼我們在handler函數中要加入event
形參,這個是必須要傳的
注:
<1> = <Button-1> =<ButtonPress-1>
<2> = <Button-2> = <ButtonPress-2>
<3> = <Button-3> =<ButtonPress-3>
這是通用的,<>
不能省略
綁定的方式
button.bind("<Button-1>", handler)
鼠標綁定的基本應用
例子
:鼠標移動,右下方看到鼠標目前的座標
import tkinter
def moving(event):
# .x_root, .y_root是相對於整個屏幕
# 獲取x軸座標(相對於窗口)
x = event.x
# 獲取y軸座標(相對於窗口)
y = event.y
textvar = "座標 : x:%r y:%r" % (x, y)
var.set(textvar)
root = tkinter.Tk()
root.geometry("300x200")
x, y = 0, 0
var = tkinter.StringVar()
text = "座標 : x:%r y:%r" % (x, y)
var.set(text)
label = tkinter.Label(root, textvariable=var)
label.pack(anchor=tkinter.S, side=tkinter.RIGHT, padx=10, pady=10)
# 事件是鼠標移動,執行moving函數
root.bind("<Motion>", moving)
root.mainloop()
運行結果:
moving(event)中的event
是可以自定義的,但是不能沒有
鍵盤相關的事件參數
鍵盤事件 | 說明 |
---|---|
<Return> | 回車 |
<Cancel> | Break鍵 |
<BackSpace> | BackSpace鍵 |
<Tab> | Tab鍵 |
<Shift_L> | 左Shift鍵 |
<Alt_L> | 左Alt鍵 |
<Control_L> | 左Control鍵 |
<Shift_R> | 右Shift鍵 |
<Alt_R> | 右Alt鍵 |
<Control_R> | 右Control鍵 |
<Pause> | Pause鍵 |
<Caps_Lock> | Caps_Lock鍵 |
<Escape> | Escapel鍵,俗稱Esc |
<Prior> | PageUp鍵 |
<Next> | PageDown鍵 |
<End> | End鍵 |
<Home> | Home鍵 |
<Left> | 左箭頭 |
<Up> | 上箭頭 |
<Right> | 右箭頭 |
<Down> | 下箭頭 |
<Print> | Print Screen |
<Insert> | Insert鍵 |
<Delete> | Delete鍵 |
<F1> | F1鍵 |
<F2> | F2鍵 |
<F3> | F3鍵 |
<F4> | F4鍵 |
<F5> | F5鍵 |
<F6> | F6鍵 |
<F7> | F7鍵 |
<F8> | F8鍵 |
<F9> | F9鍵 |
<F10> | F10鍵 |
<F11> | F11鍵 |
<F12> | F12鍵 |
<Num_Lock> | Num_Lock鍵 |
<Scroll_Lock> | Scroll_Lock鍵 |
<plus> | 小鍵盤上的 + 鍵 |
<minus> | 小鍵盤上的 - 鍵 |
<asterisk> | 小鍵盤上的 * 鍵 |
<slash> | 小鍵盤上的 / 鍵 |
<key> | 任意鍵 |
注:
<key> = <KeyPress> = <KeyRelease>
鍵盤綁定的基本應用
例子
:當我們按下Tab
時,tkinter做出響應
import tkinter
def tab(event):
# keysym 鍵盤事件對應的字符串
print(f"按下了{event.keysym}鍵")
root = tkinter.Tk()
root.geometry("100x80")
root.bind("<Tab>", tab)
root.mainloop()
運行結果:
可打印的字符
字符 | 說明 |
---|---|
<a> | 字母a |
<b> | 字母b |
此處省略剩下的24個字母 | 此處省略剩下的24個字母 |
<1> | 數字1 |
<2> | 數字2 |
此處省略剩下的8個數字 | 此處省略剩下的8個數字 |
<A> | 按鍵shift+a或者字母大寫A |
<B> | 按鍵shift+b或者字母大寫B |
此處省略剩下的24個大寫字母 | 此處省略剩下的24個寫字母 |
注:
<a> = <Key-a> = <KeyPress-a> = <KeyRelease-a>
打印字符的基本應用
例子
:當我們按下a
時,tkinter做出響應
import tkinter
def tab(event):
print(f"按下了{event.keysym}鍵")
root = tkinter.Tk()
root.geometry("100x80")
root.bind("<a>", tab)
root.mainloop()
運行結果:
組合鍵
組合鍵 | 說明 |
---|---|
<Shift-Home> | Shift+Home |
<Alt-Home> | Alt+Home |
<Control-Home> | Ctrl+Home |
<Control-A> | Ctrl+shift+a |
注:
組合鍵不止這些,可以自由組合
組合鍵的基本應用
例子
:當我們按下Alt+Home
時,tkinter做出響應
import tkinter
def tab(event):
print(f"按下了home鍵")
root = tkinter.Tk()
root.geometry("100x80")
root.bind("<Alt-Home>", tab)
root.mainloop()
運行結果:
窗體事件
窗體事件 | 說明 |
---|---|
<Configure> | 改變大小或位置 |
<Visibility> | 當組件變爲可視狀態時觸發 |
<Unmap> | 當組件由顯示狀態變爲隱藏狀態時觸發 |
<Map> | 當組件由隱藏狀態變爲顯示狀態時觸發 |
<Expose> | 當組件從原本被其他組件遮蓋的狀態中暴漏出來時觸發 |
<FocusIn> | 組件獲得焦點時觸發 |
<FocusOut> | 組件失去焦點時觸發 |
<Circulate> | 當窗體由於系統協議要求在堆棧中置頂或壓底時觸發 |
<Colormap> | 當窗體的顏色或外貌改變時觸發,Tk中忽略此細則 |
<Property> | 當窗體的屬性被刪除或改變時觸發,屬於TK的核心 |
<Destroy> | 當組件被銷燬時觸發 |
<Activate> | 與組件選項中的state項有關,表示組件由不可用變爲可用時觸發 |
<Deactiavte> | 與組件選項中的state項有關,表示組件由可用變爲不可用時候觸發 |
窗體事件綁定的基本應用
例子
:獲得焦點與失去焦點,由Tab鍵進行切換
import tkinter
def a(event):
label.config(text="獲取焦點")
def b(event):
label.config(text="失去焦點")
root = tkinter.Tk()
root.geometry("300x200")
btu = tkinter.Button(root, text="Click")
btu.pack(anchor=tkinter.W)
btu.bind("<FocusIn>", a)
btu.bind("<FocusOut>", b)
btu1 = tkinter.Button(root, text="Other")
btu1.pack(anchor=tkinter.W)
label = tkinter.Label(root, bg="lightgreen", fg="red", height=2, width=12, font="Times 16 bold")
label.pack()
root.mainloop()
運行結果:
例子
:組件由隱藏狀態變爲顯示狀態,顯示狀態變爲隱藏狀態
from tkinter import *
def show(event):
b2.config(bg="lightyellow")
# SystemButtonFace 默認的顏色,就是那個灰色
b1.config(bg="SystemButtonFace")
def Unshow(event):
b1.config(bg="lightblue")
b2.config(bg="SystemButtonFace")
root = Tk()
l1 = Label(root, text='pack_forget')
b3 = Button(root, text='按鈕')
b3.bind("<Unmap>", Unshow)
b3.bind("<Map>", show)
# pack_forget 不顯示
b1 = Button(root, text='隱藏', command=b3.pack_forget)
b2 = Button(root, text='顯示', command=b3.pack)
l1.pack(fill=X)
b1.pack(fill=X)
b2.pack(fill=X)
b3.pack()
root.mainloop()
運行結果:
Event
Event | 說明 |
---|---|
widget | 事件被觸發的控件 |
.x, .y | 鼠標距離窗體左上角的位置(座標) |
.x_root, .y_root | 鼠標距離屏幕左上角的位置(座標) |
.char | 鍵盤事件對應的字符代碼 |
.keysym | 鍵盤事件對應的字符串 |
.keycode | 鍵盤事件對應的按鍵碼 |
.num | 鼠標事件對應的按鍵碼 |
.width, .height | 控件的新大小 |
.type | 事件類型 |
Event的基本應用
例子
:鍵盤輸入,tkinter響應字符串和按鍵碼(ASCII)
import tkinter
def show(event):
print(f"{event.keysym}對應的ASCII碼:{event.keycode}")
win = tkinter.Tk()
win.geometry("150x100")
win.bind("<Key>", show)
win.mainloop()
運行結果:
對於ASCII的說明
每套鍵盤可能對應的ASCII都不同,所以在這裏我並沒有寫明每個字母、字符、數字的ASCII值,即使寫了可能也與大家的ASCII值不同,怎樣得知自己鍵盤的ASCII值呢?
上述的方法獲取是最好驗證的,請參照Event的基本應用
中的例子
取消綁定
取消綁定xx
的方法如下:
# <xxx>是綁定方式
xx.unbind("<xxx>")
例子
:
import tkinter
def show(event):
label.config(text="ForPython!")
def choose(x):
if var.get():
x.bind("<Button-1>", show)
else:
label.config(text="")
x.unbind("<Button-1>")
root = tkinter.Tk()
root.geometry("300x200")
btu = tkinter.Button(root, text="Click")
btu.pack(anchor=tkinter.W)
var = tkinter.BooleanVar()
cbut = tkinter.Checkbutton(root, text="bind/unbind", variable=var, command=lambda: choose(btu))
cbut.pack(anchor=tkinter.W)
label = tkinter.Label(root, bg="lightgreen", fg="red", height=2, width=12, font="Times 16 bold")
label.pack()
root.mainloop()
運行結果:
一個事件綁定多個事件處理程序
使用bind()
方法可以綁定一個事件處理程序,tkinter也允許我們執行一個事件綁定多個事件處理程序,同樣使用bind()
方法,但是新增加的時間處理程序需要在bind()方法內增加參數add = "+"
例子
:
import tkinter
def show():
print("???")
def shower(event):
print("!!!")
root = tkinter.Tk()
button = tkinter.Button(root, text="Click", command=show)
button.pack()
button.bind("<1>", shower, add="+")
root.mainloop()
程序會先執行bind()
綁定的程序,然後再執行Button()
內command
指定的程序
Protocols
Protocols 可以翻譯爲通信協議
,在tkinter內可以解釋爲窗口管理程序
(Windows Manager)與應用程序
(Application)之間的通信協議
。tkinter也支持使用綁定概念更改此通信協議
例子
:退出程序詢問是否要退出
import tkinter
from tkinter import messagebox
def show():
res = messagebox.askokcancel("提示", "請問您確定要退出嗎?")
if res:
root.destroy()
else:
return
root = tkinter.Tk()
root.protocol("WM_DELETE_WINDOW", show)
root.mainloop()
運行結果:
謝謝觀看,筆者會持續更新,如有錯誤或者建議,請私信我