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