# Linking Events to Callback Functions
我不會嘗試完全解釋Tk和Tkinter的事件綁定。 我已經讀過幾本書和許多有關該主題的網頁,但感覺不太熟練。
將事件綁定到小部件是使用Tk和Tkinter的一個非常令人困惑的方面。 Tk實現了全局綁定層次結構,因為Tk允許在操作之間創建綁定,并且
1. 特定小部件內的事件,例如鼠標選擇和特定按鈕,
2. 特定類別的小部件內的事件,例如鼠標選擇和應用程序中的所有按鈕,
3. 頂層窗口中所有窗口小部件中的事件,以及
4. 應用程序中所有小部件內的事件。
PAGE實際上僅輔助第一種綁定。 至少一位受人尊敬的文檔撰寫者建議不要使用其他三篇。 如果您覺得有必要對綁定進行分類,則可以將其手動添加到支持模塊中的“ init”功能中。
Grayson在他的書中談到了直接或間接調用回調。 指定命令屬性將導致間接調用,而指定綁定命令將導致直接調用。 不同之處在于,直接調用將事件對象傳遞給回調,并且回調函數必須具有包含該事件參數的參數列表。 要查看直接和間接調用回調的示例,請參見vrex示例或bind示例。 人們還可以將它們描述為清晰而混亂,或者簡單而復雜。 首先讓我討論一種簡單的情況,即指定命令屬性。
許多小部件都有一個command屬性,該屬性指定了用Button-1選擇小部件時要執行的代碼。 對于使用Button-1選擇小部件的常見情況,這是一種簡化的綁定方式。 雖然Tk允許指定一個代碼塊,但必須堅持使用Python中的函數調用。 例如,將按鈕的命令屬性設置為“ foo”,以便選擇Button-1將導致不帶參數的函數“ foo”的調用。
如果要調用一個函數并將參數傳遞給它,則可以使用lambda表達式。 請參閱Grayson的書第6.4節,詳細了解在這種情況下使用lambda表達式。 (簡而言之,如果Python遇到后跟括號的函數名稱,它將嘗試立即執行該函數,而在事件發生時則需要執行。)假設您要調用函數foo并將其3傳遞給 一個參數,您作為命令輸入的是
~~~
lambda : foo(3)
~~~
不是
~~~
foo(3)
~~~
或傳遞可變參數
~~~
lambda x: foo(x)
~~~
不是
~~~
foo(x)
~~~
要指定這樣的命令,請選擇一個小部件,然后在“屬性編輯器”中的“命令”字段中輸入該命令。 為了保持具有完成大多數事情的太多方式的Virtual Tcl風格,一種替代方法是使用Button-3在Widget Tree中選擇Widget,然后選擇Widget-> Set Command。 我不經常使用替代方法。 除了這一段之外,我可能會忘記它。
當指定Entry小部件或Tk_entry小部件的“ validatecommand”和“ invalidcommand”選項時,命令字符串必須是一個元組,第一個元素是命令名稱,其他元素限于:
* %d = 動作類型(1 =插入,0 =刪除,其他為-1)
* %i =要插入/刪除的char字符串的索引,或-1
* %P = 條目的值(如果允許編輯)
* %s = 編輯前的輸入值
* %S = 插入或刪除的文本字符串(如果有)
* %v =當前設置的驗證類型
* %V = 觸發回調的驗證類型
(key, focusin, focusout, forced)
* %W = 小部件的tk名稱
每個元素都用引號引起來。 例如:
~~~
(vcmd, '%P', '%S', '%W')
~~~
因此,將發生的情況是,PAGE函數將在支持模塊中由PAGE創建一個骨架函數vcmd,其中可變數量的參數以entry的值作為第一個參數,插入的字符串作為第二個參數,而widget信息作為第三個參數。 請注意,%W不會傳遞小部件,而是將小部件轉換為字符串。 我認為這是tkinter中的錯誤。 在tkinter中,它的行為肯定不同于在Tcl / Tk中的行為。
骨架函數如下所示:
~~~
def vcmd(*args):
print('v2_support.vcmd')
for arg in args:
print ('another arg:', arg)
sys.stdout.flush()
return True
~~~
請注意,驗證函數必須返回True或False。
簡單案例的綁定就這么多了,該案例本質上定義了一個配置命令,用于在生成的Python中設置小部件的command屬性。為了將其他事件綁定到窗口小部件,我將指向構建窗口的Bindings窗口。當然,可以在支持模塊的init功能中手動編碼bind命令。
對于許多小部件而言,command屬性是必經之路,并且很容易將視為關聯的事件。實際上,是關聯的事件。差異可能很重要。例如,“復選框”窗口小部件將關聯變量設置為新值,作為事件的最后一步。
另一個建議是,雖然command屬性通常會傳遞零個參數或lambda函數中指定的參數。對于Scale和TScale小部件,將scale的最終值作為第一個參數傳遞給回調函數。看到[Scale and TScale](use.md)
哎呀哎呀视频在线观看