2006年10月17日
#
在swing中
FileSystemView.getFileSystemView().getSystemDisplayName(file);
FileSystemView.getFileSystemView().getSystemIcon(file);
可以采用上面的方法得到。
那SWT中如何做到呢?
說(shuō)到GUI類庫(kù)的重用有一個(gè)很著名的模式:Composite模式。對(duì),一個(gè)現(xiàn)代面向?qū)ο驡UI類庫(kù)基本上都有這個(gè)模式的實(shí)現(xiàn),當(dāng)然也包括swing.不
過(guò)早一點(diǎn)如MFC就沒(méi)有完整的實(shí)現(xiàn),現(xiàn)在來(lái)看如果一個(gè)GUI類庫(kù)連基本的Composite模式都沒(méi)有實(shí)現(xiàn)基本上感覺(jué)是出土的文物啦!
但是我們來(lái)看即便有了Composite模式,但Composite模式通常是構(gòu)建靜態(tài)組合,如果要?jiǎng)討B(tài)的替換一個(gè)復(fù)合組件內(nèi)部的子元素如何辦呢?如此一來(lái)這個(gè)組件就只能定義自己的布局形式,而不能定死在這個(gè)布局形式內(nèi)的元素。
其實(shí)從用戶角度來(lái)說(shuō)一個(gè)GUI元素通常就是兩種情況要么就是表現(xiàn),要么就是處于和用戶交互狀態(tài),這是它們的形態(tài)通常不一樣。所以組件不僅僅要只定義自己的布局形式,還要給于外部機(jī)會(huì)來(lái)配置當(dāng)自己的子元素處于這兩種狀態(tài)時(shí)相應(yīng)的UI組件是什么!
swing通過(guò)renderer/editor達(dá)到了這種靈活性。如swing中JTable,JList,JTree等組件都只是定義了自
己的布局形式。并且都可以配置renderer/editor,這樣你的renderer/editor實(shí)現(xiàn)就接管了組件里面元素的表現(xiàn)形式和交互形態(tài)。
理論上你可以用任何JComponent作為組件里面元素的表現(xiàn)形式和交互形態(tài)。其靈活性和重用性達(dá)到了一個(gè)巔峰!
以前還聊過(guò)一個(gè)JTable的例子!
http://www.douban.com/group/topic/1112689/
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
String er = layout.getEditorArea();
layout.setEditorAreaVisible(false);
layout.addView(FileTransfersView.DownloadID,IPageLayout.TOP , 0.25f, er);
layout.addView(FileTransfersView.UploadID,IPageLayout.BOTTOM , 0.25f, er);
}
}
比如有以上代碼,那么我如何獲得被加到layout的viewer實(shí)例呢?我發(fā)現(xiàn)本更無(wú)法獲得viewer實(shí)例的引用了。
plugin.xml文件的片斷
<extension
point="org.eclipse.ui.views">
<view
class="com.mt.ui.FileTransfersView"
id="com.mt.ui.FileTransfersView.Upload"
name="test1"/>
<view
class="com.mt.ui.FileTransfersView"
id="com.mt.ui.FileTransfersView.Download"
name="test2"/>
</extension>
很明顯兩個(gè)view的class是一個(gè),因?yàn)槲乙赜眠@個(gè)view,它們只是有些屬性和背后的數(shù)據(jù)不一樣!我需要在初始化時(shí)將這些不一樣設(shè)定。
如果我的機(jī)會(huì)只有在這里
public void createPartControl(Composite parent) {
}
那么難道不同的View就要都通過(guò)繼承,然后重寫(xiě)上面這個(gè)方法來(lái)做,這樣的話是不是過(guò)于呆板了!
還請(qǐng)熟悉eclipse RCP的指點(diǎn)。
最近看Eclipse RCP稍微了解一下JFace,看了它的MVC架構(gòu)有感!
在JFace的ContentViewer抽象中下面的三個(gè)方法反映它對(duì)待模型的思路:
public void setContentProvider(IContentProvidercontentProvider)
public void setInput(Object input)
public void setLabelProvider(IBaseLabelProvider labelProvider)
顯然setInput是用來(lái)配置view背后的數(shù)據(jù),從它的參數(shù)類型(Object)來(lái)講應(yīng)該是你的與view無(wú)關(guān)的領(lǐng)域模型.
從這里就可以看出它和swing的根本差異.swing各種不同viewer(在swing的世界叫JComponent)背后的模型是因不同組件而不同的,模型的接口是反應(yīng)了該組件特征的.
如 JTable 背后的TableModel,TableModel接口的定義基本表達(dá)了作為一個(gè)二維表格期望獲得數(shù)據(jù)的方式如TableModel中有定義這樣的方法:
Objetc getValueAt(int row,int column)
在JFace中直接可以放入Object類型數(shù)據(jù),但各種viewer不一樣對(duì)于拿數(shù)據(jù)的期望也不一樣,
ContentProvider,LabelProvider解決了上述問(wèn)題,不同ContentProvider定義了該viewer所期望的拿數(shù)據(jù)的接口,其實(shí)我覺(jué)得swing中的model在意義上類似于ContentProvider.
其實(shí)感覺(jué)JFace的做法在盡量強(qiáng)制你必須構(gòu)建獨(dú)立于GUI的模型.
而swing的話并沒(méi)有這種侵入性,你可以直接實(shí)現(xiàn)viewer的模型接口如
class Mymodel implenents TableModel{
?。?
也可以定義比較獨(dú)立的模型然后用對(duì)象適配器模式將它們適配到viewer model上!
http://www.douban.com/group/topic/1159250/
我很希望B/S快點(diǎn)退出歷史舞臺(tái)!
建設(shè)一個(gè)client and server多對(duì)多的互聯(lián)網(wǎng)環(huán)境。并且client的部署和B/S一樣方便,甚至你可以沒(méi)有client的概念,而只有獲得服務(wù)的概念。
放眼過(guò)去,.net戰(zhàn)略最為接近。
我不明白為什么很多認(rèn)為基于瀏覽器等的所謂Web OS會(huì)大放光彩。
顯然由OS延伸來(lái)構(gòu)造一個(gè)互聯(lián)網(wǎng)應(yīng)用平臺(tái)合理的多。
傳統(tǒng)we作為運(yùn)行平臺(tái)有先天的不足!
就從傳統(tǒng)web說(shuō)起,一個(gè)html瀏覽器(client)<---->html提供者(web服務(wù)器)。也就是它也只是傳統(tǒng)C/S架構(gòu)一
種,只是它基于標(biāo)準(zhǔn)而帶來(lái)了普及性,使得html瀏覽器(client)逐步演變?yōu)橐粋€(gè)基礎(chǔ)設(shè)施(平臺(tái))。很多應(yīng)用在往這個(gè)架構(gòu)上移,于是基于這個(gè)架構(gòu)的
被稱為B/S的架構(gòu)出現(xiàn)了。然而很遺憾,它原先并不是作為互聯(lián)網(wǎng)應(yīng)用平臺(tái)角度而設(shè)計(jì)的,于是就有了以下的感慨:
縱觀web的歷程,就是在一個(gè)不適合交互的基礎(chǔ)架構(gòu)上搭建交互。
扭曲的發(fā)展!
強(qiáng)扭的瓜的感覺(jué)。
所以我們要的是一個(gè)更為通用的互聯(lián)網(wǎng)應(yīng)用平臺(tái),它應(yīng)該吸取B/S的URL的想法,但是他指向的是實(shí)際的程序,并被下載到本地運(yùn)行。但這個(gè)過(guò)程某種程度上被透明,所以對(duì)用戶來(lái)說(shuō)他完全可以沒(méi)有client的概念!當(dāng)然他首先應(yīng)該有這樣一個(gè)互聯(lián)網(wǎng)應(yīng)用平臺(tái)。
其實(shí)這就是讓用戶直接可以面向服務(wù),面向服務(wù)是個(gè)好概念,所以它并不局限于人于機(jī)器之間。軟件不同的組件之間或不同應(yīng)用之間(可分布在不同物理設(shè)備上)可以面向服務(wù)的概念集成在一起------即SOA.其中已多對(duì)多,松耦合為特點(diǎn)。
實(shí)際上通過(guò)一個(gè)執(zhí)行環(huán)境(運(yùn)行時(shí))去統(tǒng)一所有的計(jì)算設(shè)備已經(jīng)被認(rèn)為是不可行的,曾經(jīng)的很多分布式架構(gòu)以及java都試圖這樣做,java希望世界所有的計(jì)算設(shè)備上都運(yùn)行著java,并都通過(guò)java來(lái)交流。很遺憾,java沒(méi)有做到。
所以SOA來(lái)了,就目前來(lái)說(shuō) web 服務(wù) 被認(rèn)為是實(shí)現(xiàn)SOA的良好架構(gòu),而 web
服務(wù)的核心是什么,不管怎么說(shuō)我覺(jué)得XML必是其一,而XML又是基于公共標(biāo)準(zhǔn)的。這里的關(guān)鍵為了實(shí)現(xiàn)應(yīng)用之間的互聯(lián)互通,我們無(wú)需要兩個(gè)應(yīng)用都構(gòu)架于同
一個(gè)執(zhí)行環(huán)境(運(yùn)行時(shí)),因?yàn)槲覀儍H將我們將要在線上交換的信息達(dá)成一致。
這就帶來(lái)了松耦合,及強(qiáng)大的靈活性。在SOA下信息孤島確實(shí)可以被很好的解決。
所以有人說(shuō)SOA之于企業(yè)應(yīng)用,就如同TCP/IP之于互聯(lián)網(wǎng)。
其實(shí)html有今天的普及,也是因?yàn)樗且粋€(gè)基于文本的公共標(biāo)準(zhǔn)的消息格式不依賴于執(zhí)行環(huán)境,但是它的設(shè)計(jì)目標(biāo)性太強(qiáng)不具有通用性的要求。因?yàn)樗婚_(kāi)始就是為一個(gè)具體的應(yīng)用架構(gòu)而設(shè)計(jì)的。然而后面對(duì)于它的要求不斷拓寬,甚至希望它能變
成一個(gè)運(yùn)行平臺(tái)于是xxxscript開(kāi)始了,但是這時(shí)實(shí)際上已經(jīng)存在了執(zhí)行環(huán)境的依賴了,因?yàn)椴煌瑇xxscript有不同的執(zhí)行環(huán)境
所以這時(shí)就有這個(gè)網(wǎng)頁(yè)怎么在這個(gè)瀏覽器上不能打開(kāi)的這樣的說(shuō)法了。而反過(guò)來(lái)雖然有了xxxscript但是還是受到B/S架構(gòu)的很多
限制(B/S的頁(yè)面模型)。所以與其不倫不類還不如將與人打交道的最終客戶端直接置身于本地的執(zhí)行環(huán)境中,并且這個(gè)執(zhí)行環(huán)境要具備“使得client的部
署和 B/S一樣方便,甚至你可以沒(méi)有client的概念,而只有獲得服務(wù)的概念。”
如果對(duì)這個(gè)執(zhí)行環(huán)境美其名曰一下:那么就叫它RIA平臺(tái)吧!
顯然這個(gè)東西沒(méi)有一個(gè)公共的標(biāo)準(zhǔn),所以幾路人馬現(xiàn)在是各自而戰(zhàn),來(lái)打造這一平臺(tái),并且進(jìn)行部署。
如Flex那一路,在部署的時(shí)候搞的是:悄悄的進(jìn)行,打搶的不要。因?yàn)槭悄壳爸髁鳛g覽器都裝有flash player,等于無(wú)形中它的RIA平臺(tái)已經(jīng)部署好了。
而MS顯然是大張旗鼓:我是老大我怕誰(shuí)。一句話,因?yàn)閷?duì)MS來(lái)說(shuō)vista就是RIA平臺(tái)。當(dāng)然細(xì)分一下應(yīng)該是其上的.net平臺(tái)來(lái)支撐RIA。因?yàn)镸S原有在桌面OS的壟斷地位,使得它將.net融于vista以大兵團(tuán)作戰(zhàn),成敗在此一舉!
不管怎么說(shuō),vista比起其他幾路人馬,確實(shí)是最完整,最強(qiáng)大的RIA平臺(tái)。
b/s增強(qiáng)前臺(tái)交互能力的方向意味著什么,意味著在要有更強(qiáng)的描述行為邏輯的語(yǔ)言(程序設(shè)計(jì)語(yǔ)言)寫(xiě)的東西在本地執(zhí)行,那么這些描述行為邏輯的語(yǔ)言是不是有好多,。。。。。。???!!!!
其二,有很多應(yīng)用僅憑Http(請(qǐng)求---響應(yīng))這種交互方式不夠,比如有些是要請(qǐng)求----回調(diào),還有一些是觀察者模型的交互等
等.比如報(bào)價(jià)系統(tǒng)就是屬于這種觀察者模型的,客戶端發(fā)送某個(gè)報(bào)價(jià)信息的請(qǐng)求,那么以后這個(gè)報(bào)價(jià)一有變化服務(wù)器端就要立刻通知客戶端(這里TGP連接要一直
保持著).
其三,是UI,采用HTML描述的UI過(guò)于不足,很多應(yīng)用需要構(gòu)建豐富的UI.
如果B/S架構(gòu)做到了以上說(shuō)的,那么還是B嗎???平臺(tái)無(wú)關(guān)性又如何保證???
其實(shí)對(duì)于這個(gè)問(wèn)題應(yīng)該這么說(shuō): b/s向基礎(chǔ)平臺(tái)發(fā)展是一個(gè)扭曲的發(fā)展,
因?yàn)樗且粋€(gè)應(yīng)用架構(gòu).
而由OS延伸則更為合理.
當(dāng)然如果某個(gè)應(yīng)用符合B/S架構(gòu),那么b/s當(dāng)然是不錯(cuò)的選擇.只是它向基礎(chǔ)平臺(tái)發(fā)展是一個(gè)扭曲的發(fā)展.(再次強(qiáng)調(diào)!)
或者這個(gè)話題可以這么說(shuō):
希望b/s向基礎(chǔ)平臺(tái)發(fā)展可以快點(diǎn)結(jié)束了!
我們來(lái)看一個(gè)問(wèn)題。
定義一個(gè)描述信息(內(nèi)容)的語(yǔ)言的標(biāo)準(zhǔn)(HTML,XML...),和定義一個(gè)一統(tǒng)的程序語(yǔ)言(java ,c,c++,c#,.................)的標(biāo)準(zhǔn)哪一個(gè)容易。
事實(shí)告述我們應(yīng)該是前者。也就是說(shuō)Application背后的運(yùn)行環(huán)境注定是多樣性的。
那么web為什么能跨平臺(tái)呢?因?yàn)樗鼈児蚕淼氖乔罢?,一個(gè)HTML標(biāo)準(zhǔn),HTML不是Application。然而扭曲就從這里開(kāi)始,HTML不斷擴(kuò)展在向Application演進(jìn),隨之跨平臺(tái)特性不斷削弱。
那么這樣一個(gè)演化說(shuō)明了什么呢?說(shuō)明我們需要Application,且它要像web一樣易部署。我們可以稱使得這樣的Application得以運(yùn)行的平臺(tái)為互聯(lián)網(wǎng)應(yīng)用平臺(tái)。
但Application終究有很多不同的平臺(tái),互聯(lián)網(wǎng)應(yīng)用平臺(tái)也不例外。但我們想想web演化的最后是不是還是難逃Application平臺(tái)的多樣性呢?。ǘ宜叩穆放で亩啵?
所以問(wèn)題關(guān)鍵回到了誰(shuí)將最有可能成為互聯(lián)網(wǎng)應(yīng)用平臺(tái)的老大,目前來(lái)看實(shí)力最強(qiáng)還是vista.
其實(shí)個(gè)人感覺(jué)vista一大使命就是要將傳統(tǒng)OS延伸成一個(gè)互聯(lián)網(wǎng)應(yīng)用平臺(tái),很多人似乎忽略了MS的這個(gè)野心。
Tim Berners-Lee的說(shuō)Web是一個(gè)"信息空間"。很精辟!
但我們更需要互聯(lián)網(wǎng)是一個(gè)"服務(wù)空間",技術(shù)一點(diǎn)的話叫"Application空間",只是這些Application要以服務(wù)的方式提供出去.所以人性化的講法叫"服務(wù)空間".
當(dāng)然提供信息也是服務(wù),所以前者是后者的一個(gè)子集!
都知道java的字符編碼方案是采用unicode的。
比如 String test = "test 編碼";
那么"test 編碼"是采用unicode編碼后的二進(jìn)制形式保存。
然而如果要把test輸出到系統(tǒng)邊界以外的地方,那么都可能要涉及到編碼轉(zhuǎn)換問(wèn)題,無(wú)論是文件還是網(wǎng)絡(luò)的另一端。
不過(guò)沒(méi)關(guān)系,java提供了強(qiáng)大的I/O庫(kù),有Reader 和 Writer兩個(gè)適配器體系,我們可以將test以我們想要的編碼方案輸出。
但是如果將test的東西輸出到界面時(shí)到有些問(wèn)題了,本來(lái)從概念上界面也是系統(tǒng)的邊界,所以u(píng)nix有一切皆文件的抽象,當(dāng)然如果界面是交互
性GUI時(shí)這個(gè)抽象顯然是不夠的,這就不論了。關(guān)鍵是GUI系統(tǒng)并沒(méi)有提供類似javaI/O的這種能力,java也沒(méi)有直接以u(píng)nicode形式輸出給
GUI系統(tǒng),而是好像會(huì)把內(nèi)存中變量字符再通過(guò)系統(tǒng)默認(rèn)語(yǔ)言(字符集)編碼去轉(zhuǎn)換,然后扔給繪圖系統(tǒng)吧!
這樣的話如果 JLable label = new JLabel(test);
那么這個(gè)label的顯示在簡(jiǎn)體中文版的OS上沒(méi)問(wèn)題,但如果在繁體中文版的OS可能就有問(wèn)題了。
按理說(shuō)swing是獨(dú)立于本地OS的GUI系統(tǒng),但是他還是建立在java2D上,而java2D還是要利用本地的繪圖系統(tǒng),像渲染文字這種繪圖是不是java2D還是利用了本地繪圖系統(tǒng)呢!
java GUI “?” “口” 這兩個(gè)我都碰到過(guò)。
如果某中編碼方案里沒(méi)有這個(gè)文字,java會(huì)用" ?"這個(gè)代替。
如果某種文字沒(méi)有相應(yīng)的字體,java會(huì)用"口"代替。
java在輸出到系統(tǒng)界面時(shí)會(huì)把內(nèi)存中變量字符再通過(guò)系統(tǒng)默認(rèn)語(yǔ)言(字符集)編碼去轉(zhuǎn)換!
我覺(jué)得如果java自己實(shí)現(xiàn)所有unicode支持的文字的繪圖(基于更低級(jí)的圖形API),那么他沒(méi)有必要轉(zhuǎn),因?yàn)閡nicode字符給java圖形系統(tǒng),他都能把它表現(xiàn)出來(lái),當(dāng)然java圖形系統(tǒng)基于OS的更低級(jí)的圖形API。
是不是java自己實(shí)現(xiàn)所有unicode支持的文字的繪圖這項(xiàng)任務(wù)比比較困難。
如果java能做到這樣真的很強(qiáng)大?。?
這樣的話JLable label = new JLabel(test); 無(wú)論在什么語(yǔ)言版的OS 都OK。
說(shuō)到MVC,大家都知道他是構(gòu)建GUI的有力模型。不過(guò)MVC本身比較抽象和寬泛,所以對(duì)于它的實(shí)現(xiàn)有很多。
swing對(duì)于MVC的實(shí)現(xiàn)用一句話來(lái)說(shuō)就是:一個(gè)GUI組件對(duì)應(yīng)著一個(gè)MVC體系。
在這個(gè)體系當(dāng)中JComponent這樣的組件就扮演者M(jìn)VC中的C,那拿JTable來(lái)說(shuō),MVC 就是 TableModel JTable TableUI.
這種將MVC幾乎實(shí)施到每一個(gè)GUI元素的設(shè)計(jì)相當(dāng)?shù)撵`活.對(duì)于swing 的MVC還有一個(gè)重要的特點(diǎn)就是它對(duì)于model
作了進(jìn)一步的區(qū)分,那就是真正表達(dá)程序數(shù)據(jù)的model,和僅僅表達(dá)界面狀態(tài)的model.還拿JTable 來(lái)說(shuō)就是: TableModel 與
TableColumnModel.
在很多地方看到都說(shuō)swing的這種MVC的劃分多被科學(xué)家欣賞,這我就不能茍同了,我是普通人,不過(guò)我也很欣賞.swing高雅而又不失實(shí)用.
當(dāng)然也有人會(huì)說(shuō)盡管swing的MVC很精彩,不過(guò)通常我們程序中model都不是僅僅對(duì)應(yīng)在一個(gè)GUI元素上,甚至不能確定要對(duì)應(yīng)在哪些GUI元素上.
定義這樣的類通常仍然很死:
class MyModel implements TableModel,ListModel{
}
我覺(jué)得對(duì)于swing的設(shè)計(jì)沒(méi)有什么錯(cuò),它為每一個(gè)組件期待的model定義了相應(yīng)的接口.但是我們程序當(dāng)中的model又希望更獨(dú)立于GUI.
為了達(dá)到兩全其美,到可以使用Eclipse里面的IAdaptable
機(jī)制.讓你的model具有 IAdaptable能力,這樣你就可以將它隨便適配到哪個(gè)swing model 上.如此的組合真是從頭到腳的靈活性.
還有swing的這種MVC設(shè)計(jì)也促成了swing的可插拔外觀特性.
不管你的項(xiàng)目是否用到了Swing技術(shù),我都要說(shuō),Swing是一個(gè)設(shè)計(jì)優(yōu)秀的Java包,它充滿了大師的智慧。如果你學(xué)了Java卻連一個(gè)
Button還不會(huì)寫(xiě),就象你學(xué)習(xí)Visual
Basic卻不會(huì)用Button,那可絕對(duì)是不能被原諒的。Swing技術(shù)的應(yīng)用已經(jīng)在國(guó)外大行其道,由于java的免費(fèi)、易學(xué)以及大家對(duì)于java技術(shù)
的充分信賴,好多公司早早的就把應(yīng)用程序的一切,從后臺(tái)服務(wù)到前臺(tái)人機(jī)交互界面,統(tǒng)統(tǒng)移到了java開(kāi)發(fā)上。Swing出現(xiàn)了快10年了,憑借其先進(jìn)的設(shè)
計(jì)思想,一直未曾落后于哪種語(yǔ)言的界面開(kāi)發(fā)技術(shù),使用和理解Swing的設(shè)計(jì)思想,對(duì)軟件開(kāi)發(fā)者大有裨益。
Swing的設(shè)計(jì)是MVC的典范。雖然MVC的概念有點(diǎn)泛濫,可是真正能夠理解并熟練掌握、在設(shè)計(jì)和開(kāi)發(fā)里面自然流露的并不多見(jiàn)。記得用VC
++開(kāi)發(fā)程序時(shí)候,MFC向?qū)б彩巧蒁ocument和View兩個(gè)類,當(dāng)時(shí)一直奇怪為什么這么繞圈子。再看Swing的設(shè)計(jì),則到處充滿了MVC的痕
跡。仔細(xì)研究Swing中事件監(jiān)聽(tīng)、Model-View分離、Renderer/Editor機(jī)制、可插拔的LookAndFeel等機(jī)制,簡(jiǎn)直就是一
門(mén)藝術(shù),充滿了美感。而如果你非常痛恨這些設(shè)計(jì)并覺(jué)得他們怪異,很可能你是剛從VB或者Delphi轉(zhuǎn)過(guò)來(lái),這些快速開(kāi)發(fā)工具幫助了你也“害”了你。
Swing設(shè)計(jì)的不錯(cuò),不過(guò)可能過(guò)度學(xué)術(shù)化的設(shè)計(jì)也使得Swing跑起來(lái)并不靈巧,學(xué)習(xí)難度也大。這客觀上確實(shí)使得Swing一直沒(méi)有被廣泛
使用,而且廣受詬病。記得以前“Swing有什么成功的應(yīng)用嗎?”之類的帖子一直是熱門(mén)話題。IBM等則趁機(jī)抓住小辮子弄了SWT吸引了不少人,使得
Java GUI技術(shù)面臨分裂的危險(xiǎn)。
不過(guò)隨著JAVA的不斷升級(jí)和優(yōu)化,Swing的速度一直在提高,美觀性也在改善,基于Swing的成功應(yīng)用也越來(lái)越多了。關(guān)于Swing是否消亡或被SWT代替或是否能作桌面應(yīng)用的爭(zhēng)論逐漸少了。不過(guò)喜歡并精通Swing技術(shù)的開(kāi)發(fā)者,尤其在國(guó)內(nèi),依舊非常少。
好在情況在轉(zhuǎn)好。Sun正意識(shí)到Eclipse和SWT所帶來(lái)的威脅,下了大力氣發(fā)展NetBeans,其最新版本對(duì)Swing
GUI可視化設(shè)計(jì)的支持已經(jīng)超過(guò)了所有對(duì)手,其Rich
Client框架也走向成熟,這對(duì)Swing的發(fā)展和應(yīng)用是一個(gè)很大的推動(dòng)。隨著WEB熱潮的減退,人們又更多的開(kāi)始理性的思考B/S和C/S架構(gòu)的選
擇,某些領(lǐng)域Swing技術(shù)已經(jīng)成為首選的解決方案。
隨著JGoodies、JIDE、TWaver等優(yōu)秀Swing產(chǎn)品的不斷涌現(xiàn),Swing會(huì)以更快速度在桌面應(yīng)用中普及。
轉(zhuǎn)載之
http://blog.csdn.net/solo/archive/2006/05/12/725635.aspx
領(lǐng)域視圖是指:某個(gè)領(lǐng)域功能對(duì)應(yīng)的交互界面。
界面體系視圖是指:是指某種組織這些領(lǐng)域視圖的UI方案。如MDI(多內(nèi)部窗口)如以前的word等,還有像現(xiàn)在eclipse的面板分割方案,docking等等。
那么將兩者做嚴(yán)格的區(qū)分有什么好處呢?
很顯然可以獲得領(lǐng)域視圖的獨(dú)立性,以達(dá)到適應(yīng)多種界面體系的靈活性,甚至在運(yùn)行時(shí)進(jìn)行界面體系的切換。
在swing中有時(shí)候我們常常有這樣的寫(xiě)法;
MyInternalFrame extends JInternalFrame{
}
其實(shí)這種寫(xiě)法是比較死的,因?yàn)橄馢InternalFrame這種view是屬于界面體系視圖范疇的東西。
如果我們的界面體系不采用InternalFrame風(fēng)格時(shí),改動(dòng)量是很大的。
其實(shí)如果這樣是不是更好呢!
interface DomainObject{
JComponent getDomainView();
}
不同的界面體系模塊拿到DomainView時(shí)以自己的方式對(duì)DomainView進(jìn)行包裝。比如是內(nèi)部桌面的話就將DomainView塞到JInternalFrame里,以JInternalFrame包裝之。
在文檔中對(duì)JTable 解釋是:用來(lái)顯示和編輯規(guī)則的二維單元表。
也就是說(shuō)JTable的類型定義決定了它是一個(gè)規(guī)則的二維單元表,但是對(duì)于二維單元表內(nèi)單元格的顯示和編輯組件的選擇又是極其靈活的.
有如下兩個(gè)接口:
TableCellEditor
Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column);
TableCellRenderer
Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column)
所有實(shí)現(xiàn)這兩個(gè)接口的對(duì)象都可以配置到JTable.JTable自身定義了單元格的狀態(tài):表現(xiàn)或編輯.
當(dāng)JTabel處于表現(xiàn)狀態(tài)時(shí)它會(huì)調(diào)用
ableCellRenderer的Component getTableCellRendererComponent(JTable
table, Object value, boolean isSelected, boolean hasFocus, int row, int
column)請(qǐng)求表現(xiàn)組件.
當(dāng)JTabel處于編輯狀態(tài)時(shí)它會(huì)調(diào)用TableCellEditor的Component
getTableCellEditorComponent(JTable table, Object value, boolean
isSelected, int row, int column);請(qǐng)求編輯組件.
這樣我們實(shí)現(xiàn)TableCellEditor,TableCellRenderer這兩個(gè)接口就可以靈活的控制表格單元格的編輯和顯示.
當(dāng)然為了方便swing已經(jīng)定義了這兩個(gè)接口的默認(rèn)實(shí)現(xiàn),如DefaultCellEditor,DefaultTableCellRenderer.
雖然我們有了靈活控制編輯和表現(xiàn)的接口,但是如何控制編輯和表現(xiàn)狀態(tài)的轉(zhuǎn)換呢!
首先單元格可不可以編輯由表格的模型控制。因?yàn)橥ǔ?刹豢梢跃庉嬋Q于數(shù)據(jù)內(nèi)容,所以將它定義在模型中是合理的!
TableModel 接口有如下一個(gè)方法:
boolean isCellEditable(int rowIndex, int columnIndex) ;
JTabel會(huì)通過(guò)他來(lái)確定可不可以編輯。
在可編輯的情況下,通過(guò)JTabel的 boolean editCellAt(int row, int column) ,可以啟動(dòng)單元格進(jìn)入編輯狀態(tài)。那么如何控制從編輯狀態(tài)退出呢?
這個(gè)稍微復(fù)雜一點(diǎn),因?yàn)閺木庉嫚顟B(tài)退出還很可能意味著要將編輯器的內(nèi)容放入表格模型。
這里有一個(gè)接口
public interface CellEditor{
void addCellEditorListener(CellEditorListener l)
Object getCellEditorValue()
void removeCellEditorListener(CellEditorListener l)
void cancelCellEditing()
boolean stopCellEditing()
.................
}
TableCellEditor繼承自它,也就是說(shuō)swing對(duì)單元格編輯器作了更抽象的定義。因?yàn)椴粌H僅是表格需要編輯。這里有個(gè)監(jiān)聽(tīng)器的注冊(cè)方法,看一下CellEditorListener的定義
public interface CellEditorListener extends EventListener
{
void editingCanceled(ChangeEvent e)
void editingStopped(ChangeEvent e)
}
很顯然編輯狀態(tài)結(jié)束的關(guān)鍵在CellEditor上。你可以主動(dòng)發(fā)出事件通知CellEditorListener說(shuō)結(jié)束了。也可以由外部調(diào)用
void cancelCellEditing()
boolean stopCellEditing()
觸發(fā)。而CellEditorListener得到通知后通??梢哉{(diào)用
Object getCellEditorValue()來(lái)獲得編輯器的值。例如JTable 就實(shí)現(xiàn)了CellEditorListener,當(dāng)你將你的TableCellEditor設(shè)置到JTable時(shí),JTable就會(huì)注冊(cè)上去。
有了靈活控制編輯和表現(xiàn)的接口,也有了控制編輯和表現(xiàn)狀態(tài)的轉(zhuǎn)換機(jī)制.不過(guò)完全從這些接口開(kāi)始構(gòu)建一套自己的實(shí)現(xiàn),也是很累的。顯然swing已經(jīng)有一套比較通用的實(shí)現(xiàn)。
首先看一下對(duì)于控制編輯和表現(xiàn)狀態(tài)的轉(zhuǎn)換,JTable有自己的一套定義,在外部事件觸發(fā)下單元格編輯和表現(xiàn)狀態(tài)的轉(zhuǎn)換,比如在單元格上雙擊
會(huì)使得該單元格進(jìn)入編輯狀態(tài),當(dāng)編輯狀態(tài)的單元格失去焦點(diǎn)時(shí),該單元格離開(kāi)編輯狀態(tài)進(jìn)入表現(xiàn)狀態(tài)。在同一時(shí)刻只有一個(gè)單元格可以進(jìn)入編輯狀態(tài)等。
再來(lái)看一下DefaultTableCellRenderer和DefaultCellEditor
DefaultTableCellRenderer繼承JLabel實(shí)現(xiàn)TableCellRenderer 接口。也就是說(shuō)表格通常的單元格表現(xiàn)都是JLabel組件。
這個(gè)實(shí)現(xiàn)其實(shí)有一個(gè)巧妙之處,在實(shí)現(xiàn)
Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column) {
。。。。。。。。。。。
return this;
}這個(gè)方法中
最后一句return this;表明不管單元格有多少,JLabel對(duì)象一直只有一個(gè),只是針對(duì)不同的單元格JLabel對(duì)象的狀態(tài)不一樣,但實(shí)例只有一個(gè),儉省很多資源。
DefaultCellEditor繼承AbstractCellEditor,而AbstractCellEditor
實(shí)現(xiàn)了TableCellEditor。這里順便講一下,swing對(duì)很多接口的實(shí)現(xiàn)都有這兩個(gè)層次,對(duì)于default的都是一個(gè)可用的實(shí)現(xiàn),而
Abstract多是抽象類,他只實(shí)現(xiàn)了接口的一部分,而這一部分通常都是很通用的。如果覺(jué)得default不能滿足要求,而覺(jué)得實(shí)現(xiàn)整個(gè)接口又麻煩,
Abstract的就很有用。
DefaultCellEditor有三個(gè)構(gòu)造函數(shù):
DefaultCellEditor(JCheckBox checkBox)
DefaultCellEditor(JComboBox comboBox)
DefaultCellEditor(JTextField textField)
因?yàn)榫庉嫴幌癖憩F(xiàn)那么單純,通常使用編輯器的對(duì)象(如JTable)都要獲得編輯器的值,然而不同編輯器的對(duì)外接口又是非常繁多的,所以CellEditor有這樣一個(gè)方法
Object getCellEditorValue()
;也就是說(shuō)使用編輯器的對(duì)象(如JTable)不管實(shí)際編輯器有多繁雜,它就只通過(guò)Object
getCellEditorValue()這個(gè)方法獲取值。那么當(dāng)你要把你的編輯器用到比如JTable上,那么就要考慮如何將你的編輯器接口適配到
JTable期望的Object getCellEditorValue() 上。
DefaultCellEditor的構(gòu)造函數(shù)就是一個(gè)提供了可以將三種編輯器進(jìn)行適配。其實(shí)這是一種適配器模式。也就是DefaultCellEditor可以適配三種編輯器。
忽略了一個(gè)很重要的問(wèn)題,就是如何將我們的編輯器或表現(xiàn)器注冊(cè)到JTable上?
這個(gè)看是很簡(jiǎn)單的問(wèn)題,其實(shí)也并非想象當(dāng)中那么簡(jiǎn)單。
先看一下JTable提供的明顯的注冊(cè)接口
void setCellEditor(TableCellEditor anEditor) ;
void setDefaultEditor(Class<?> columnClass, TableCellEditor editor)
void setDefaultRenderer(Class<?> columnClass, TableCellRenderer renderer)
第一個(gè)接口很顯然整個(gè)表格單元格的編輯器將由這個(gè)注冊(cè)的編輯器接管。
后面兩個(gè)是基于數(shù)據(jù)類型進(jìn)行配置的,也就是說(shuō)這種數(shù)據(jù)類型的單元格編輯器將由注冊(cè)的編輯器接管。
那么如何決定數(shù)據(jù)類型呢?看表格模型TableModel里有一個(gè)方法
Class<?> getColumnClass(int columnIndex);
很明顯和是否可編輯一樣,數(shù)據(jù)類型由模型決定。
除此之外還有另外的注冊(cè)方法,那就是表格本身也是有其他元素組成,在JTable中下一級(jí)元素是列,TableColumn。它有這兩個(gè)方法
void setCellEditor(TableCellEditor cellEditor)
void setCellRenderer(TableCellRenderer cellRenderer)
可以將編輯器和表現(xiàn)器直接注冊(cè)在列上,那么這一列的編輯或表現(xiàn)將由你注冊(cè)的東西接管。