#
在swing中
FileSystemView.getFileSystemView().getSystemDisplayName(file);
FileSystemView.getFileSystemView().getSystemIcon(file);
可以采用上面的方法得到。
那SWT中如何做到呢?
说到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/
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的指点。
最近看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/
我很希望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.
虽然我们有了灵活控制编辑和表现的接口,但是如何控制编辑和表现状态的转换呢!
首先单元格可不可以编辑由表格的模型控制。因为通常可不可以编辑取决于数据内容,所以将它定义在模型中是合理的!
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)
可以将编辑器和表现器直接注册在列上,那么这一列的编辑或表现将由你注册的东西接管。