<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ### 8.3.2 事件處理 GUI 應用程序的核心是對各種交互事件的處理程序。應用程序一般在完成建立圖形界面 等初始化工作后都會進入一個事件循環,等待事件發生并觸發相應的事件處理程序。Tkinter 程序通過 mainloop 方法進入事件循環,而事件與相應事件處理程序之間是通過綁定建立關聯 的。 最常見的綁定形式是針對構件實例的: ``` <構件實例>.bind(<事件描述符>,<事件處理程序>) ``` 其語義是:若針對&lt;構件實例&gt;發生了與&lt;事件描述符&gt;相匹配的事件,則調用&lt;事件處理程序&gt;。 調用事件處理程序時,系統會傳遞一個 Event 類的對象作為實際參數,該對象描述了所發生 事件的詳細信息。 事件處理程序一般都是用戶自定義的函數。這種函數在應用程序中定義,但不由應用程 序調用,而是由系統調用,所以一般稱為回調(callback)函數。 GUI 應用程序經常封裝為類,在這種情況下,事件處理程序常常定義為應用程序類的方 法。我們將在 8.4.1 中通過例子詳細介紹這種做法。 先看一個處理鼠標點擊事件的例子: 【程序 8.6】eg8_6.py ``` from Tkinter import * def callback(event): print "clicked at", event.x, event.y root = Tk() f = Frame(root, width=100, height=100) f.bind("<Button-1>", callback) f.pack() root.mainloop() ``` 本程序在根窗口中添加了一個框架構件,然后把框架構件與&lt;Button-1&gt;事件進行了綁定, 對應&lt;Button-1&gt;事件的回調函數是 callback,意思是每當在框架中點擊鼠標左鍵時,都將觸發 callback 執行。系統執行 callback 時,將一個描述事件的 Event 類對象作為參數傳遞給該函數, 該函數從事件對象參數中提取點擊位置信息并在控制臺輸出類似“clicked at 44 63”的信息。 鍵盤事件與焦點 當圖形界面中存在許多構件時,如果是用鼠標直接點擊某個窗口或構件,程序自然就知 道要操作哪個構件。但如果是按一下鍵盤,應該由哪個構件做出響應呢?GUI 引入了“焦點” 概念:圖形界面中有唯一焦點,任何時刻只能有一個構件占有焦點,鍵盤事件總是發送到當 前占有焦點的構件。焦點的位置可以通過構件的 focus_set()方法來設置,也可以用鍵盤上的 Tab 鍵來輪轉。因此,鍵盤事件處理比鼠標事件處理多了一個設置焦點的步驟,如下例所示: 【程序 8.7】eg8_7.py ``` from Tkinter import * def printInfo(event): print "pressed", event.char root = Tk() b = Button(root,text = 'Press any key') b.bind('<Key>',printInfo) b.focus_set() b.pack() root.mainloop() ``` 本程序創建了一個按鈕構件,該按鈕與按任意鍵事件&lt;Key&gt;進行綁定,事件處理程序是 回調函數 printInfo。此程序的 b.focus_set()語句將按鈕設為鍵盤焦點,從而按下任何鍵都會由 按鈕響應,并觸發 printInfo 函數來處理事件,處理過程是顯示按下的鍵的字符。讀者可以思 考一下:本例中綁定的是&lt;Key&gt;事件,運行時如果輸入上檔鍵(如@#$%^&之類)會出現什 么結果呢? 綁定到多個事件 一個構件可以響應多種事件,例如下面這個程序同時響應鼠標和鍵盤事件: 【程序 8.8】eg8_8.py ``` from Tkinter import * def callback1(event): print "pressed", event.char def callback2(event): f.focus_set() print "clicked at", event.x, event.y root = Tk() f = Frame(root, width=100, height=100) f.bind("<Key>", callback1) f.bind("<Button-1>", callback2) f.pack() root.mainloop() ``` 此程序在根窗口中創建一個框架構件,并為框架構件同時綁定了任意鍵事件&lt;Key&gt;和鼠 標左鍵事件&lt;Button-1&gt;。運行此程序,先在框架中點擊鼠標,從而觸發 callback2 函數的執行, 該函數又將框架設置為鍵盤焦點。此后,按下任何鍵都將觸發 callback1 函數的執行,其功能 是顯示所按的字符。運行此程序后如果沒有在框架中先點擊鼠標,則框架未獲得焦點,也就 不會對鍵盤事件進行處理。 當構件綁定的多個事件之間具有“特殊與一般”的關系,總是調用最“近”的事件處理 程序。例如,如果將某構件與任意鍵事件&lt;Key&gt;綁定,相應事件處理程序是 h1,又與回車鍵 事件&lt;Return&gt;綁定,相應事件處理程序是 h2,那么當按下回車鍵時,處理此事件的將是 h2。 綁定層次 前面三個例子中都是針對某個構件實例進行事件綁定,稱為“實例綁定”。實例綁定只對 該構件實例有效,對其他實例——即使是同類型的構件——是無效的。除了實例綁定,Tkinter 還提供了其他事件綁定方式。實際上,Tkinter 中共有不同層次的四種綁定方法: + 實例綁定:綁定只對特定構件實例有效,用構件實例的 bind 方法實現。 + 類綁定:綁定針對構件類,故對該類的所有實例有效,可用任何構件實例的 bind_class 方法實現。例如,為使 Button 類的所有實例都以同樣方式響應回車鍵事件,可執行: ``` root.bind_class("Button","<Return>",callback) ``` + 窗口綁定:綁定對窗口(根窗口或頂層窗口)中的所有構件有效。用窗口的 bind 方 法實現,例如為使窗口中所有構件都以同樣方式響應鼠標右鍵點擊事件,可執行: ``` root.bind('<Button-3>',callback) ``` + 應用程序綁定:綁定對應用程序中的所有構件都有效。用任一構件實例的 bind_all 方法實現。例如,很多應用程序在運行時可以隨時按下 F1 鍵以使用戶得到幫助信 息,這可以通過建立 F1 鍵的應用程序綁定來實現: ``` root.bind_all('<F1>',printHelp) ``` 下面這個例子演示了事件傳遞與綁定層次結合所帶來的后果: 【程序 8.9】eg8_9.py ``` from Tkinter import * def printInstance(event): print 'Instance:',event.keycode def printToplevel(event): print 'Toplevel:',event.keycode def printClass(event): print 'Class:',event.keycode def printApp(event): print 'Application:',event.keycode root = Tk() b = Button(root,text = 'Press Return') b.bind('&lt;Return&gt;',printInstance) b.winfo_toplevel().bind('&lt;Return&gt;',printToplevel) root.bind_class('Button','&lt;Return&gt;',printClass) root.bind_all('&lt;Return&gt;',printApp) b.pack() b.focus_set() root.mainloop() ``` 本程序中定義了四個層次的事件綁定,運行此程序并按下回車鍵,將得到如圖 8.24 所示 的輸出。這是因為&lt;Return&gt;事件首先被擁有焦點的按鈕實例 b 捕獲,并執行 printInstance 函 數。此后,&lt;Return&gt;事件還將向 b 的各級上層傳遞,從而依次被 b 所屬的 Button 類、b 所屬 的頂層窗口 root、b 所屬的應用程序這三個層次捕獲,分別導致 printClass、printTopleve 和 printApp 三個函數的執行。 ![](https://box.kancloud.cn/2016-02-22_56cafce65ccd8.png) 圖 8.24 多層綁定 關于程序 8.9 還有幾點要說明:(1)程序中的 b.winfo_toplevel()方法返回 b 所屬的頂層構 件,本例中即根窗口 root;(2)對程序代碼與輸出結果進行比較后可看出,事件的傳遞層次 與程序中綁定語句的次序沒有關系;(3)類綁定與應用程序綁定可以通過任何構件來設置, 因此將上面程序中的 root.bind_class 和 root.bind_all 改成 b.bind_class 和 b.bind_all,結果也是 一樣的。 協議處理 用過 Word 的讀者都知道,如果編輯了文檔還沒有保存就去關閉程序窗口,Word 會彈出 一個對話框,詢問用戶是否要保存當前文檔。如果我們希望利用事件綁定到事件處理程序來 實現這種功能,就面臨一個問題:“關閉窗口”并不屬于前面介紹過的事件類型,因此無法用 事件綁定來處理。 為此,Tkinter 提供了一種稱為“協議處理”的機制,用于應用程序處理來自操作系統窗 口管理器的協議消息。處理過程是這樣的:當用戶企圖關閉窗口,操作系統的窗口管理器就 會生成一條 WM_DELETE_WINDOW 的協議消息并發送給應用程序,應用程序再調用相應的 處理程序來處理這條消息。 窗口構件有一個稱為 protocol 的方法,用于定義對協議消息的處理程序: ``` <窗口構件>.protocol("WM_DELETE_WINDOW",<處理程序>) ``` 其中窗口構件可以是根窗口或頂層窗口,處理程序是函數或方法。如此定義之后,當用戶試 圖關閉窗口時,我們自己的處理程序就會接管控制。處理程序可以彈出一個消息框詢問用戶 是否要保存當前數據,或者干脆忽略關閉窗口的請求。處理完畢之后,可以在處理程序中完 成關閉窗口的操作,方法是調用窗口的 destroy 方法。例如: 【程序 8.10】eg8_10.py ``` from Tkinter import * from tkMessageBox import * def callback(): if askokcancel("Quit","Do you really wish to quit?"): root.destroy() root = Tk() root.protocol("WM_DELETE_WINDOW", callback) root.mainloop() ``` 虛擬事件 我們也可以自定義新的事件類型,稱為虛擬事件。虛擬事件的形式是&lt;&lt;事件名稱&gt;&gt;,可 利用構件的 event_add 方法來創建。例如,如果想為構件 w 創建一個新事件&lt;&lt;MyEvent&gt;&gt;, 該事件由鼠標右鍵或鍵盤上的 Pause 鍵觸發,則執行下列語句: ``` w.event_add("<<MyEvent>>","<Button-3>","<KeyPress-Pause>") ``` 此后就可以像系統定義的事件一樣使用了。例如: ``` w.bind("<<MyEvent>>",myHandler) ``` 在構件 w 上點擊右鍵或按下 Pause 鍵都會觸發函數 myHandler。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看