java皮肤swing_Java Swing 皮肤

标签只需要一个value属性,该属性定义了实际的组件状态。假如没有指定value,如清单3和4所示,那么每种状态都使用默认值。假如指定value属性,那么能够选择ENABLED、MOUSE_OVER、PRESSED、DISABLED、FOCUSED、SELECTED和DEFAULT。这些选择包含Swing中任何组件任何可能的状态。您还能够在不同选择间添加and来组合各种状态。例如,假如您想在鼠标位于按钮之上连同按钮被按下的时候改变按钮上的字体,那么能够使用状态值MOUSE_OVER and PRESSED。清单5展示了用于处理demo应用程式状态的XML。注重每种状态是怎样定义不同的图像和文本颜色的。清单5.处理状态处理标签的一个重要方面是知道哪些组件有哪些状态。显然,在这个例子中,按钮能够拥有默认状态、鼠标悬停(mouse-over)状态和被按下(pressed)状态。对于这个例子,还能够定义一个聚焦(focused)和禁用(disabled)状态。但是对于一个面板,选中(selected)状态根本不适用,当鼠标处于面板之上时假如改变面板的状态,那么只能招来抱怨。处理特定于组件的属性定义对每种组件都通用的XML属性时,总是忽略了一些特定于组件的属性。例如list的行高、单选钮的图标和菜单的箭头图标,这些都是特定于组件的属性。能够定义的特定于组件的属性有100多种,但是为每个这样的属性定义一个XML属性就有些过分了。因此,Synth XML文档答应配置特定于组件的属性。标签就像一个Hashtable,他定义一个键/值对来配置属性。登录屏幕示例的复选框演示了怎样为特定于组件的属性编写代码。通过定义imageIcon,能够配置默认状态和选中状态下的CheckBox.icon。这就像是翻遍100个属性找到您想要的属性那样简单。清单6展示了为登录屏幕中特定于组件的属性编写代码的XML。注重要首先定义imageIcon。然后,通过使用图像图标的ID,能够为复选框的每种状态配置一个图标。清单6.定义特定于组件的属性使用定制painter定义图2中登录屏幕例子的最后工作是用曲线绘制渐变背景。用XML来实现这种背景似乎有些别扭,坦白地说,真是这样。但这样我便有机会展示Synth,不限制您在UI设计中只使用图像和简单的颜色。您能够使用他来画任何东西。Synth答应重写其paint方法(即在javax.swing.plaf.synth.SynthPainter类中的方法),该方法继续自SynthPainter,他将覆盖那些您想要定制绘画方式的特定函数。在这个例子中,需要定义paintPanelBackground方法,因为这种设计不能以Synth XML格式描述。为了使用定制的painter,或在XML中以任何方式创建一个类,能够使用标签。标签答应创建和保持用于弥补Synth呈现程式的任何Java类。标签带有两个元素:class:将创建的类的全名。id:用于在XML文档中引用这个类实例的ID名。通过使用对象,不但能够创建BackgroundPainter类的实例――这个类将用于绘制背景,而且还能够创建ColorUIResource类的实例,在这个类中能够定义背景颜色。想一想:在BackgroundPainter类中定义背景中使用的颜色,这和Synth的目标是矛盾的,Synth的目标是在一个外部XML文档中定义一切,而不是在一个Java文档中进行硬编码。使用定制painter的最后一步是告诉Synth呈现引擎,是您自己而不是SynthPainter类来提供函数。在这个例子中,首先在BackgroundPainter类中定义paintPanelBackground函数,并让SynthPainter类定义剩下的绘画函数。标签让您能够覆盖SynthPainter函数。他带有两个元素:method:定制painter应该覆盖的方法。从使用图像一节中您已得知,您能够在javax.swing.plaf.synth.SynthPainter类中找到这些函数,但是应该删除每个函数开始部分的paint字符串(例如,SynthPainter中的paintPanelBackground在XML文档中应该是panelBackground)。id:对将覆盖此方法的类的引用。为了在定制painter中使用颜色,必须将颜色保存在javax.swing.UIDefaults类中。在清单7和清单8中能够看到,将颜色保存在UIDefaults中十分简单,对于那些接触过UI创建的人来说应该,应该比较熟悉这些内容。在XML文档中定义的键将成为UIManager中的引用,在BackgroundPainter的Java代码中,能够使用UIManager来获得颜色。清单7展示了在例子应用程式中使用定制painter的XML代码。注重必须首先定义颜色。清单7.使用定制painter12080清单8展示了例子应用程式的定制绘画类的Java代码:清单8.定制绘画的Java代码public class BackgroundPainter extends SynthPainter{public void paintPanelBackground(SynthContext context,Graphics g, int x, int y,int w, int h){Color start = UIManager.getColor("Panel.startBackground");Color end = UIManager.getColor("Panel.endBackground");Graphics2D g2 = (Graphics2D)g;GradientPaint grPaint = new GradientPaint((float)x, (float)y, start,(float)w, (float)h, end);g2.setPaint(grPaint);g2.fillRect(x, y, w, h);g2.setPaint(null);g2.setColor(new Color(255, 255, 255, 120));g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);CubicCurve2D.Double arc2d = new CubicCurve2D.Double(0, h/4, w/3, h/10, 66 * w, 1.5 * h, w, h/8);g2.draw(arc2d);g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);}}更高级的配置本节包含两个超出登录屏幕例子范围的技术。在创建您自己的Synth外观时,您可能发现这两项技术很有用。绘制非Swing组件能够改变每个Swing组件的外观这一点虽然很棒,但是还应该能够改变其他组件――研发人员创建的用于填补Swing空缺的组件――的外观。在这种情况下,标签需要作出改变,以反映正在绘制的不是个Swing组件。type属性能够有两种值:假如映射到一个Swing组件,则该值为region,假如映射到非Swing组件,则该值为name。因此,假如将标签变为,则会改变每个类名以Custom开始的组件(例如,CustomTextField或CustomLabel),使他们使用mystyle式样。式样的分层结构除了在创建XML文档时使用KISS式样之外,还能够构建分层次的一些式样,并将这些式样应用于组件中。清单9应该能够清楚地演示这一点。注重,Synth使用最后定义的属性来显示组件。清单9.分层结构的例子清单9中的代码使每个组件有一个黑色的背景,字体大小为14,但label组件除外,label组件拥有红色的背景。通过克隆sublevel中的base式样,清单9复制了整个式样。然后,您能够覆盖所需的任何特定属性。检验Synth的性能、可靠性和效率至此,您已看到怎样创建用于Synth的XML文档,连同怎样通过更改字体、更改颜色和添加图像来创建定制的外观,但对于Synth可能更有些疑问。假如您使用Swing已有一段时间,那么我能够肯定,您首先想到的是性能问题。我设计了一些性能测试,这些测试表明,Synth不会令您的UI慢如蜗牛。为了调查您可能看到的问题(并讨论我在使用Synth时已碰到过的一些问题),我查看了Java Bug Parade(请参阅参考资料)。最后,我将回答最重要的问题―― Synth真的能够节省您的时间吗?装载那么多图像会不会使Synth变得更慢?为了回答这个问题,我创建了两个测试,并让您更深切地体会Synth在性能方面和其他外观的比较。第一个测试将测试示例登录应用程式的装载时间。该测试装载6个Synth图像,并将这个装载时间和一个研发人员可能创建的一般屏幕的装载时间进行比较。第二个测试是关于装载时间的压力测试――一个帧中有100多个组件。两个测试都将测试Ocean和Motif外观的装载时间,以便进行比较。为了公正起见,我在三种机器上运行了这两个测试――一种是安装的手提电脑,一种是SuSE linux box,更有一种是Red Hat Linux box。结果显示在表1和表2中。表1.登录屏幕的平均装载时间机器配置OceanMotifSynthWindows XP - 1.7GHz - 2GB RAM .32 seconds .29 seconds .57 secondsSuSE Linux 9.0 - 3.3GHz - 2GB RAM .23 seconds .20 seconds .45 secondsRed Hat Linux 3.0 - 1.4GHz - 512MB RAM .37 seconds .32 seconds .61 seconds表2.包含100个组件的屏幕的平均装载时间机器配置OceanMotifSynthWindows XP - 1.7GHz - 2GB RAM .33 seconds .32 seconds .34 secondsSuSE Linux 9.0 - 3.3GHz - 2GB RAM .23 seconds .23 seconds .30 secondsRed Hat Linux 3.0 - 1.4GHz - 512MB RAM .40 seconds .40 seconds .43 seconds您能够看到,Synth外观的装载时间只比Ocean和Motif慢一点点。但是请注重,登录屏幕和压力测试会比装载更慢一些。乍一看来,这似乎很希奇,但假如仔细研究,便能够发现起因。压力测试没有装载复选框中所使用的图像,而登录屏幕却装载了这些图像。据此能够下结论,在Synth外观中使用的每个附加图像增加了装载时间。和含有两个使用两种不同图像的组件的应用程式相比,使用相同图像的100个组件装载起来要更快一些。减少所使用图像的数量能够提高Synth装载时间方面的性能。Synth是不是像Swing相同,在第一次发布时满是bug?根据Sun Java研发者网站上Bug Parade的评判,Synth看上去是个比较干净、没有bug的产品。然而,没有哪个软件是完美的。Synth曾有125个bug,这和Synth处理JTabbedPane的方式不成比例。因此,假如您经历到一些问题,不要感到惊奇。然而,根据Sun的辩护,这些缺陷都处于“关闭(Closed)”状态。但通常的情况是,假如以前存在某些问题,那么这些问题在将来也很可能会出现。虽然bug 数据库为Synth赋予了一个相对干净的形象,我在处理登录屏幕的时候还是碰到一些问题。我第一次尝试更改JPanel背景颜色时遭到失败。我创建了一个特定于JPanel的式样,并将其绑定到任何JPanel,但这样行不通。而当我决定使用自己的定制painter时,事情就解决了。一个更大的问题是当状态改变时对组件进行重新绘制。在处理按钮及其状态时,我发现,按钮上的文本不能正确地改变颜色。当初始化时,作为默认颜色的白色没有如期显示,并且直到触发了状态变化之后才出现,然后就被重新配置为默认颜色。假如仔细研究关于Synth的文档,就能够发现这个小花絮:“虽然能够为每种状态提供不同的字体,但在一般情况下,当组件的状态变化时,组件不会重新生效,所以,假如您试图为不同状态使用有明显不同大小的字体时,有可能会碰到字体大小的问题”。听起来似乎他们遇上了试图让Synth使用老的Swing代码的问题。因此,假如要在状态改变时更改字体,那么要小心。Synth看上去的确很少有bug。但假如随处出点小问题,那些本应该行得通的代码就会行不通,我不会对此感到惊奇。但是,变通的办法不难找到。对于在工作中碰到的每个问题,我总能找到一个变通的办法。利用Synth能够创建出完全专业的外观吗?回答是肯定的。Java 1.4中发布的GTK+和Windows XP外观就完全是用Synth创建的。(那时他不是个已公开的API。)所以这方面显然没有问题。用Synth创建一个完整的外观比用Java代码编写这样的外观要快多少?这很轻易计算。这两种方法各自都包含两个步骤:创建外观,这通常是由图像设计人员负责的工作。将图像界面转化成代码。不管是用Java编写代码还是使用Synth,图像界面设计这部分工作所花的时间是相同的。根据我创建定制外观的经验,我估计为一个应用程式创建一个完整的外观需要两个图像设计人员两周的时间。也就是说,图像设计工作需要4人一周(person-week)的人力。通常,根据我的经验,通过类继续的方式将图像界面成立即可用的外观需要三个Java编程人员花大约两个月的时间。也就是说,编写Java代码需要6个人一个月(person-month)的人力。加上图像界面设计工作,通过重写UI类,用Swing创建一个完全定制的外观总共需要7个人一个月的工作量。这些数据有助于您明白为什么Internet上可供下载的定制外观是那么少。通过将图像界面转换成一个XML文档,Synth能够节省大量的时间。通过Java编程创建外观需要6个人一个月的工作量,而一个研发人员将图像界面转换成Synth XML文档只需两个星期。用Synth创建完整外观所需的工作量减少到仅仅6个人一周的工作量――通过使用Synth节省了超过5个月的时间。对于一个由两个图像设计师和两个程式员组成的团队,在短短三个星期内便能够创建出一个完整的Synth外观。结束语Synth将皮肤的概念引入到Swing中。相对于传统的用Java代码编写定制外观的方法,Synth最大的优势是节省时间。一个完整的Swing外观能够在不到一个月的时间里完成,这比用Java语言编程的方法要快5倍。对于有干劲的研发人员,在用Java代码编写一个外观的时间里,他能够创建5个Synth外观。然而,Synth并非毫无瑕疵。通过编写Java代码覆盖Swing外观,能够同时改变应用程式的外观和感觉。而Synth只答应改变应用程式的外观。这是个很大的不同之处。外观是指应用程式中使用的颜色、字体和图像。另一方面,感觉则对应于应用程式在交互期间展现出来的行为――这里指单击一下鼠标右键,那里按下一个键。例如,假如您想改变一个JList的行为,希望通过单击鼠标左键选中条目,然后再通过单击鼠标右键来删除条目,那么用Synth是无法做到这些的。您需要为新的外观编写Java代码。Synth实际上应该称为一种新的Swing外观,而不是一种普通外观。通过Synth能够快速改变UI的外观,但UI的感觉永远都是默认的Swing感觉。当然,假如您想通过为应用程式提供新的外观来使之整洁漂亮,或渴望看到比令人讨厌的Metal外观(谢天谢地,在Java 5.0中他已成为历史)更好的Swing应用程式外观,那么Synth是很好的一个选择。他不存在性能问题,并且看上去bug也很少。Sun已表示,通过发布GTK+外观,用Synth能够创建完整的外观。令人吃惊的是,Synth文档和实例现在还很少。阅读本文之后,对于Synth的工作原理您应该有一个更深的理解,并且能够使用一个组件一个样式标签(one-style-tag-per-one-component)的设计来生成一个完整的Synth XML文档。Synth的继续和分层模型为创建style标签提供了更强大的方法,但没有他们仍然能够创建完整的外观。理想情况是:随着对Synth熟悉的加深,Swing UI社区将出现皮肤数量的大爆炸。有了数百个可供选择的外观,通常那些加在Swing应用程式身上的“长相恐怖”、“丑陋”之类的责骂之词也将永远消失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值