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

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

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

    Java Focus實現(xiàn)紀要一

    Posted on 2008-10-21 11:08 英雄 閱讀(1186) 評論(0)  編輯  收藏
     

     

    Java Focus實現(xiàn)紀要一

    窗口系統(tǒng)一般包含一個桌面GUI+若干應(yīng)用程序GUI。每個GUI都由組件構(gòu)成,每個組件都可以獲得focus,獲得focus的組件將獲得之后的鍵盤事件,而任意時刻只有一個組件能獲得focus。這個設(shè)計適用在當前所有的窗口系統(tǒng),而跨各種系統(tǒng)的JAVA應(yīng)用,其focus的表現(xiàn)也要遵循這個設(shè)計目標。

    JAVA的組件分為重量級和輕量級組件,區(qū)別在于重量級組件實例的成員peer-對等體,其行為緊密依托本地系統(tǒng)的GUI行為函數(shù)庫來進行實現(xiàn)。比如一個JFRAME,當setvisible時,會依托peer.show進行屏幕繪制行為,該行為會通過本地系統(tǒng)GUI行為函數(shù)庫完成;這樣一來,當其被點擊時,本地系統(tǒng)會依據(jù)最初調(diào)用本地GUI函數(shù)繪制時留下的信息,從而能夠經(jīng)底層處理后(比如將該鼠標事件附加peer標記信息,同時可能經(jīng)底層分析需要構(gòu)造出一個可能的focus_gain事件,則在操作系統(tǒng)層面登記當前聚焦GUI組件等)準確將底層GUI事件派送給該JVM進程,該事件因而在jvm進程中的AWT-Windows線程loop獲取到,并通過事件提供的peer標記最終確定目標為重量級組件JFRAME,因此一個source==JFRAMEAWTEvent被構(gòu)造出來并最終分派給EDT進行后續(xù)處理。

    事件機制是程序中家喻戶曉的設(shè)計模式了。但是,看javafocus實現(xiàn)中對這個機制似乎多少有些不那么絕對的清晰J

    個人理解,事件的含義就是某種定義的情況發(fā)生了。比如點擊鼠標這個動作可以說觸發(fā)了多個事件,如press,release,click等,分別指發(fā)生了鼠標button1按下,放開,完成點擊的情況。button1按下這個事件比起完成點擊就要更基礎(chǔ)一些,因為完成點擊指的是一個由按下,放開動作序列組合的情況發(fā)生了。

    那么對于focus,focus_gained,focus_lost這兩個事件應(yīng)該是指某組件獲得焦點或失去焦點的情況發(fā)生了,反映在機器里,應(yīng)該是某種指向當前聚焦組件的全局變量發(fā)生了更新。

    然而在Java awt實現(xiàn)里,概念混亂出現(xiàn)啦。

    如果awt_windows loop 到了focus事件,一,這個事件一定是目標向重量級組件的;二,此時,這個事件對于底層系統(tǒng)的對等組件,focus_gainded是發(fā)生了(底層系統(tǒng)標記當前聚焦組件的全局變量已經(jīng)更新;底層操作系統(tǒng)沒有mess,總是在真正focus改變后才分發(fā)focus事件),然而在java層面,截至到awt_windows loop 到底層focus事件并包裝成FocusEvent放置到EVENT QUEUE時,java層面并沒有更新jvm里的全局變量。所以我個人認為這個時候就不應(yīng)該包裝成FocusEvent,至少不應(yīng)該叫這個名字,應(yīng)該叫PrepareFocusEvent,嘿嘿。

    澄清事件機制的概念后,回頭看java focus 要實現(xiàn)的目標。

    1.       最簡單的設(shè)計思路是提供一個setfocus調(diào)用API,該API來更新一個全局變量。EDT每次處理一個keyevent將根據(jù)當前全局變量進行target。最后給各類組件注冊合適的事件監(jiān)聽,比如mouse press listener,在listen響應(yīng)處理中調(diào)用setfocus

    要提供setfocus指定某組件聚焦。Setfocus一旦成功返回,該組件將接受后繼發(fā)生的所有的鍵盤事件,直到再次失去焦點。

    然而問題是輕量級組件的容器是一個重量級組件,而在對輕量級組件調(diào)用setfocus時它的本地對等組件在系統(tǒng)中很可能還沒有獲得焦點。若實現(xiàn)上只是簡單的把java的全局變量更新了,那系統(tǒng)就會出現(xiàn)兩個聚焦組件:一個是底層系統(tǒng)承認的原來的某底層對等組件,一個是java里認為的現(xiàn)在的jtextfield。而本地系統(tǒng)始終把鍵盤事件派發(fā)到它認可的聚焦組件上,如果這個聚焦組件屬于另外一個C++進程,那么這些鍵盤事件就會分發(fā)給C++進程,而不會被JVMawt-windows loop到。也就是說,雖然setfocus成功返回了,但并不代表隨后的鍵盤事件會target到這個組件上。所以不能采用這樣的設(shè)計思路。

    盡管如此,實際上我們的組件的監(jiān)聽一般是在mouse_press上。而這個鼠標按下動作各類底層操作系統(tǒng)處理時一般首先分發(fā)mouse_press底層事件,然后切換焦點,再分發(fā)focus事件。隨后的鍵盤事件會在底層切換焦點后分發(fā)出去。假如我們確定下來所有GUI應(yīng)用只在EDT線程在mouse_press監(jiān)聽處理中setfocus,實際上不會丟失鍵盤事件。但是如果我們要在其他情況,比如某worker 線程中setfocus,那么setfocus就不再可靠了。

    那么,根據(jù)前面的分析,現(xiàn)在更改設(shè)計,在setfocus處理中調(diào)用底層API要求其重量級容器對應(yīng)的本地對等組件聚焦并等到它確實聚焦完成了再更新JAVA的全局變量。但這樣也有問題。即使底層系統(tǒng)根據(jù)底層調(diào)用通知更新了focus,馬上還會繼續(xù)對可能的焦點切換操作響應(yīng)(可以認為有一個系統(tǒng)進程在處理外設(shè)的響應(yīng)),很有可能別的C++應(yīng)用就在此時再要求focus,于是接著就更新了底層的focus登記;而我們的setfocus調(diào)用卻是在jvm進程的某線程中,顯然這就是個并發(fā)的情景,這樣,很有可能我們的對本地對等組件的通知發(fā)過去并返回了,那邊底層系統(tǒng)就馬上切換到了C++的某個組件focus,而我們的線程繼續(xù)更新JAVA的全局focus變量,于是雖然setfocus成功返回了,但并不代表隨后的鍵盤事件會target到這個組件上。

    現(xiàn)在看來,除非我們同步這兩個進程,讓系統(tǒng)進程等待我們的調(diào)用setfocus的線程返回,顯然那樣是不合理的。(JAVA只能服從OS,不能讓OS服從JAVA---出自《英雄亂語》J)。

    鑒于以上的分析,根本無法實現(xiàn)一個setfocus來完成一個切換焦點的原子性操作。jre1.7的實現(xiàn)為不存在setfocus,而只有requestfocus,意思是只是將這個切換焦點的請求登記上但并不進行實際切換focus;隨后等收到相應(yīng)的事件通知后再處理request并徹底完成一次focus切換。

    2.       聚焦組件后馬上獲得隨后的鍵盤事件。

    難點是按用戶的實際想法,mouse_press后,馬上就要鍵盤拼寫,鍵盤的輸入應(yīng)該targetmouse_pressjtextfield。根據(jù)前面的分析,mouse_press響應(yīng)中requestfocus/setfocus后并沒有意味著切換焦點已經(jīng)完成。若實現(xiàn)上對于后續(xù)的鍵盤事件只是簡單地根據(jù)JAVA的那個全局focus變量target,則這些鍵盤事件將不會target到期待的組件上。

    鑒于以上的分析,jre1.7的實現(xiàn)是requestfocus時,只要這個請求滿足必要條件,那么在其返回前就登記一個時間戳,在這個時間戳之后在下一個requestfocus時間戳之前,EDT 逐個取的keyevent都將target到該組件并登記,直到該組件徹底聚焦完成后,馬上把這些keyevent dispatch

    3.       需要支持TAB鍵等焦點遍歷操作。

    這一點JAVA有一個遍歷模型,如下:

    具體參照http://java.sun.com/javase/6/docs/api/java/awt/doc-files/FocusSpec.html

    該要 求并沒有難點。實現(xiàn)上只要對keyevent監(jiān)聽,并根據(jù)規(guī)則進行合適處理即可。


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


    網(wǎng)站導(dǎo)航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    主站蜘蛛池模板: 又色又污又黄无遮挡的免费视| 免费国产作爱视频网站| 国产资源免费观看| 亚洲欧洲无码AV不卡在线| 国产在线国偷精品产拍免费| 亚洲国产综合人成综合网站00| 免费成人高清在线视频| 亚洲国产精品乱码一区二区| 成人久久免费网站| 亚洲AV综合色区无码另类小说| 成全在线观看免费观看大全 | 免费看国产一级片| 亚洲AV无码专区在线观看成人| 永久黄网站色视频免费| 亚洲av无码专区亚洲av不卡| 日产乱码一卡二卡三免费| 国产精品成人亚洲| 亚洲人成色7777在线观看不卡| 亚洲黄片手机免费观看| 亚洲日韩精品射精日| 暖暖日本免费中文字幕| 亚洲春色另类小说| 成全影视免费观看大全二| 亚洲欧洲av综合色无码| 亚洲av日韩片在线观看| 国产又黄又爽胸又大免费视频| 亚洲精品国产成人99久久| 永久免费AV无码国产网站| 曰批免费视频播放免费| 亚洲国产精品高清久久久| 成人免费视频网站www| 无码亚洲成a人在线观看| 国产精品V亚洲精品V日韩精品| 成全在线观看免费观看大全| 亚洲av午夜精品无码专区| 亚洲Av无码乱码在线播放| 久久成人无码国产免费播放| 亚洲中文字幕乱码熟女在线| 久久亚洲精品无码观看不卡| 120秒男女动态视频免费| 特级毛片aaaa级毛片免费|