<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java Focus實現紀要二

    Posted on 2008-10-26 17:20 英雄 閱讀(1346) 評論(0)  編輯  收藏
     

    Java Focus實現紀要二

    1.       Jre1.7版本中,KeyboardFocusManagerDefaultKeyboardFocusManager這兩個類,Component, WComponentPeer類一起完成了focus的主要邏輯實現。

    DefaultKeyboardFocusManager是前者的系統(tǒng)默認實現。其單例注冊在appcontext,如果需要,程序員可以替代它,以擴展focus的邏輯實現。

    appcontext.put(KeyboardFocusManager.class, new SelfKeyboardFocusManager());

    2.       Component中提供了requestFocus方法。而各個組件在初始化時都會安裝默認的Listener。當這些Listener收到適當的事件通知后(比如mouse_press)即會調用這個方法。該方法首先判斷該組件是否focusable,組件所依托窗口是否focusable,當前聚焦組件的InputVerifier是否驗收輸入等等,判斷通過后請求重量級組件容器的peer.requestFocus。WComponentPeer中提供該requestFocus方法。該方法首先調用native processSynchronousLightweightTransfer,其會調用KeyboardFocusManager .processSynchronousLightweightTransferr,作用是如果當前request組件的重量級組件容器正對應當前底層系統(tǒng)的聚焦組件,而且當前沒有任何切換焦點的heavyweightRequests,這時將直接切換focus變量KeyboardFocusManager.focusOwner。

    如果上述調用沒有順利完成并返回true,則會調用native _requestFoucs。該方法會調用KeyboardFocusManager .shouldNativelyFocusHeavyweight,其作用就是完成request登記,并在登記時間戳以正確緩存處理后續(xù)進入EDTKeyevent處理。

    Request登記的結構為KeyboardFocusManager.heavyweightRequests=

    LinkedList< HeavyweightFocusRequest >

    -- HeavyweightFocusRequest{

    Component heavyweight;

    LinkedList<LightweightFocusRequest> lightweightRequests登記方式分為3:

    a. 如果發(fā)出requestFocus的組件的重量級組件容器正對應當前底層系統(tǒng)的聚焦組件,而且當前沒有任何切換焦點的heavyweightRequest,則增加一個heavyweightRequest并向Post-Qqeue post focus-event。

    b. 如果發(fā)出requestFocus組件的重量級組件容器不對應當前底層系統(tǒng)的聚焦組件,而且當前沒有任何切換焦點的heavyweightRequest;或者當前存在切換焦點的heavyweightRequest,而最后一個heavyweightRequest. Heavyweight!=當前request組件的重量級組件容器,則要增加一個heavyweightRequest,并同步通知底層系統(tǒng)進行重量級對等組件的focus切換。

    c. 如果當前存在切換焦點的heavyweightRequest,而且最后一個heavyweightRequest. Heavyweight==當前requestFocus的組件的重量級組件容器,則直接在request.lightweightRequests追加一個LightweightFocusRequest。

    3.       EDT在逐個處理AWTEvent時,委托給EventQueue.dispatchEvent,繼而委托給Component. dispatchEventImpl,該方法順序執(zhí)行下面的代碼片段:

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    /* focusManagerIsDispatching標志了該event;如果==true意味著該event不會交由KeyboardManager進行retargetdispatch。而這兩個動作主要完成的功能就是刷新java的全局focus變量。因此可以想象focusManagerIsDispatching==trueFocus_eventfocus發(fā)生切換后的event,而focusManagerIsDispatching==false的是PrepareFocusEvent。*/

                if (!e.focusManagerIsDispatching) {//----------PrepareFocusEvent

                // Invoke the private focus retargeting method which provides

                // lightweight Component supportF

                /*通過retargetFocus,處理之前注冊的request請求,最終激發(fā)出合適的CausedFocusEvent,交給下面的dispatch.

     */

                if (e.isPosted) {

                    e = KeyboardFocusManager.retargetFocusEvent(e);

                    e.isPosted = true;

                }

                // Now, with the event properly targeted to a lightweight

                // descendant if necessary, invoke the public focus retargeting

                // and dispatching function

    /*通過dispatch給注冊的DefaultKeyboardFocusManager,最終更新了java的全局focus變量

     */

                if (KeyboardFocusManager.getCurrentKeyboardFocusManager().

                    dispatchEvent(e))

                {

                    return;

                }

            }

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    4.       總之:

    a. 輕量級組件的Mouse_Press ListenerrequestFocus。request通過必要條件檢查后會在KeyboardFocusManager.heavyweightRequests緩存列表登記,同時在一個列表中登記一個時間戳marker=當前系統(tǒng)時間。

    b. 每一個KeyEvent都有一個發(fā)生時間when,這個發(fā)生時間認為是AWT-Windows loop底層event形成KeyEvent的時間。EDT在調用KeyboardFocusManager 。dispatchEvent處理一個KeyEvent時只要發(fā)現when晚于時間戳緩存列表中登記的第一個時間戳,就充分說明這是在某焦點切換請求發(fā)出后發(fā)生的鍵盤事件,則不應該將這個KeyEvent target到當前全局focus變量,因而這時暫將此KeyEvent緩存在另一個列表。

    c. 根據前面的分析,在requestFocus時有3種情況,一種是新增heavyweightRequest,同時postpost-queue一個FocusEvent,一種是新增heavyweightRequest,同時因為要求底層系統(tǒng)切換重量級對等體而awt-loop到一個FocusEvent,這兩種情況的request都在列表中期待對應FocusEvent到來再切換焦點。從登記時間戳開始,被awt-loop到的KeyEvent進入EDT時都將緩存下來,而一段時間后當期待的FocusEventpost-queue進入event-queue并要在EDT中處理時,有充分的條件可以判斷出此后再進入EDTKeyEvent,都至少是request登記時間戳后發(fā)生的,則這時可以完成此request-刪除該heavyweightRequest緩存條目,做focus實際切換,并將緩存的KeyEvent 及時間戳記錄處理掉。而第3種情況是在requestFocus時可以在最末一個heavyweightRequest上直接追加LightWeightReuquest,那么當該heavyweightRequest期待的FocusEvent到來時,按前面所述處理完該request,再將后續(xù)LightWeightRequest保存引用到一個全局變量KeyboardFocusManager.currentLightweightRequests,再將此刻為止awt-loop至的post-queue的所有event完全flushevent-queue,再把一個要求循環(huán)處理所有currentLightweightRequests指向的LightWeightRequestsInvocationEvent post event-queue之后。這樣當EDT開始處理該InvocationEvent時,有充分的條件可以判斷出此后再進入EDTKeyEvent,都至少是最后一個后續(xù)LightWeightRequest登記時間戳后發(fā)生的,則這時只需按該InvocationEvent執(zhí)行即可,及逐個清理LightWeightRequest完成focus切換及處理時間戳和緩存KeyEvent。如果在循環(huán)處理過程中發(fā)生對某一個組件requestFocus調用,這時會根據處理之初currentLightweightRequests中是否只有單獨1request來確定能否processSynchronousLightweightTransferr,即如果有多個,則這時禁止processSynchronousLightweightTransferr以防止破壞了切換焦點的順序。

    d. 重量級組件不需要在Mouse_Press Listener request Focus,當被進行Mouse Press時,底層系統(tǒng)分發(fā)一個Focus Event,當進入EDT處理時,在jre1.7中通過KeyboardFocusManager.retargetUnexpectedFocusEventretarget,首先逐個剔除request后進行期待匹配(針對可能的底層分發(fā)-post-queue-event-queue中間環(huán)節(jié)Event的遺漏等例外情形),如果最后沒有一個request匹配,則直接形成CausedFocusEvent交給后繼dispatch完成焦點切換。更確切地說,對于jre1.7而言組件聚焦應該都通過requestFocus完成切換,不通過該方式的聚焦切換在retarget時將歸屬到Unexpected被處理,而重量級組件的這種聚焦正好通過unexpected完成。

    5.       最后,個人認為jre1.7中存在一個可能的問題:每次dispatchEvent時都會在retargetFocusEventprocessCurrentLightweightRequests,這樣不久破壞了4-c分析的時機邏輯了么?為什么要這樣呢?


    只有注冊用戶登錄后才能發(fā)表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久99国产亚洲高清观看首页| 天堂亚洲免费视频| 国产亚洲婷婷香蕉久久精品| 成全视频免费高清| 久久99国产综合精品免费| 无人视频在线观看免费播放影院| 亚洲国产超清无码专区| 亚洲开心婷婷中文字幕| 午夜亚洲av永久无码精品| 成人免费一区二区三区在线观看| 久久精品成人免费观看| 国产日韩久久免费影院 | 亚洲一区二区观看播放| 亚洲网站在线观看| 久久精品国产精品亚洲下载| 国产aa免费视频| 在线免费观看a级片| 免费无码又爽又刺激聊天APP| 无码人妻一区二区三区免费n鬼沢 无码人妻一区二区三区免费看 | 亚洲第一AAAAA片| 青青草原亚洲视频| 亚洲国产成人久久综合碰| 国产精品免费视频播放器| 超pen个人视频国产免费观看| 成年在线观看网站免费| 91精品视频免费| aⅴ在线免费观看| 亚洲美女免费视频| 99久久综合精品免费| 日韩精品在线免费观看| 日本高清不卡aⅴ免费网站| 国产福利电影一区二区三区,免费久久久久久久精 | 国产成人无码综合亚洲日韩| 亚洲综合久久夜AV | 亚洲人成无码网WWW| 亚洲日本中文字幕天堂网| 亚洲毛片不卡av在线播放一区 | 免费国产黄网站在线观看动图| 麻豆亚洲AV成人无码久久精品 | 欧美在线看片A免费观看| 性色av无码免费一区二区三区|