??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲中文字幕无码爆乳av中文,久久精品国产精品亚洲,亚洲精品国产自在久久http://www.tkk7.com/pateric/category/6937.htmlzh-cnWed, 28 Feb 2007 07:54:18 GMTWed, 28 Feb 2007 07:54:18 GMT60最新的Swing外观Q定制UI不在话下http://www.tkk7.com/pateric/articles/27682.htmlpatericpatericThu, 12 Jan 2006 02:38:00 GMThttp://www.tkk7.com/pateric/articles/27682.htmlhttp://www.tkk7.com/pateric/comments/27682.htmlhttp://www.tkk7.com/pateric/articles/27682.html#Feedback0http://www.tkk7.com/pateric/comments/commentRss/27682.htmlhttp://www.tkk7.com/pateric/services/trackbacks/27682.html  
  在 Sun 一如既往地试䏀再ơ引?Java Desktop”之际,Java UI 开发h员的抱怨之词亦已表面化Q要创徏完全定制的外观实在太难。这样做不仅要花费太多的旉Qƈ?Swing UI 代码的编写和文档的编制也极ؓ(f)不堪Q常常是乱杂一气,~Z规划。ؓ(f)了创建完整的外观Q开发h员需要?Metal 外观?39 个类Q或者?Basic 外观?60 个类。谁想通过重写整个包来改变应用E序呈现外观的方式呢Q用 Swing 创徏定制外观有多难,通过下面的事实同样可H见一斑:(x)在很多开发h员ؓ(f)开源项目添砖加瓦的时代QInternet 上可用的自定?Swing 外观几乎是凤毛麟?—?d大约?20 个,其中数?SourceForge.net 上(请参阅参考资料)?BR>  
  丽只是肤浅的东?/B>
  
  q入 SynthQSun 希望它能使应用程序外观的个性化q程变得Ҏ(gu)。Synth 的目标很?—?让开发h员不必编写Q何代码就可以创徏新的外观。这g是个不错的解x案。程序员一般没有突出的艺术才华Q而图形设计h员通常也不?Java ~程专家。Synth 把对外观的所有描qC代码中分d来,而将其放入外部的 XML 文g和图像文件中Qؓ(f)上述问题提供了大快h心的解决之道。这U完全在外部文g中描q的外观被称作皮肤(skinQ?BR>  
  Sun 的皮肤概念ƈ不是什么创新。例如,W(xu)inamp 有数癄皮肤QFirefox 也有几十U皮肤,q些皮肤很容易创建,只需更改一?XML 文g卛_。想像一下,仅仅修改一?XML 文gQ就能快速、容易地?Java 应用E序创徏一个外观。再xq样一来的l果 —?几百个互不相同的 Swing 外观。Java UI 开发h员当然有理由Ƣ呼了?BR>  
  本文深入分?Synth 外观Q向(zhn)展C创Z个完整的外观或皮肤所需知道的一切。?zhn)会(x)看C个带有示例皮肤的应用E序Q这个应用程序用了 Synth 所有重要的概念。然后,我会(x)逐步剖析q个皮肤Q在构徏 XML 文g的过E中Q一一教会(x)(zhn)?Synth 的各个概c?BR>  
  本文最后一节将力回答开发h员关?Synth 性能、bug 和缺陷以?Synth 在省时方面的表现{种U问题。阅L文之后,(zhn)应该会(x)愿意拥护 Synth 作ؓ(f)外观解决Ҏ(gu)Qƈ准备马上使用它来创徏自己?Swing 外观?BR>  
  Synth 基础
  
  Synth 是一个白板(tabula rasaQ外?—?一块完全空白的dQ表Cؓ(f)一个完全空白的面板QpanelQ,只有?XML 文g中定义了lgӞ它才?x)显CZѝ一旦定义了lgQ在应用E序上设|?Synth 外观再Ҏ(gu)不过了,如清?1 所C:(x)
  
  清单 1. 讄 Synth 外观
  
  SynthLookAndFeel synth = new SynthLookAndFeel();
  synth.load(SynthFrame.class.getResourceAsStream("demo.xml"), SynthFrame.class);
  UIManager.setLookAndFeel(synth);
  
  但是Q对?SynthQ最重要的是要理解它?XML 代码Q而不?Java 代码。虽?Synth XML 格式一开始看上去比较吓hQ但实际上很单。如果?KISS QKeep It Simple StupidQ这道符咒,(zhn)可以快速地创徏一?XML 文gQƈ得到一个新的、可以运行的外观?BR>  
  考虑?KISS 指o(h)Q我首先介l?Synth XML 文g的主要构?—?<style> 标签?lt;style> 标签包含描述一个组件的式样的所有信息,例如颜色、字体、图像文件、状态,以及(qing)一些特定于lg的属性。虽然一?<style> 标签可以描述多个lgQ但构徏 Synth 文g的最便方法是为每?Swing lg创徏一个式栗?BR>  
  创徏好式样之后,便可以将式样链接C个组件?lt;bind> 标签通知 Synth 引擎一个已定义的式样链接到一个组Ӟ如清?2 所C。这L(fng)l合便完全创Zlg的新外观?BR>  
  清单 2. 一U式样链接到一个组?BR>  
  <style id="textfield"> 
  // describe colors, fonts, and states</style><bind style="textfield" type="region" key="Textfield"/><style id="button"> 
   // describe colors, fonts, and states</style><bind style="button" type="region" key="Button"/>
  
  关于 <bind> 标签Q要注意的一Ҏ(gu)Q?lt;bind> 标签中的 key 属性映到 javax.swing.plaf.synth.Region cM的常量。Synth 引擎使用q些帔R式样与一个实际的 Swing lg链接。简单的lgQ例?JButton ?JTextFieldQ用一个常量。有些更复杂的组Ӟ例如 JScrollBar ?JTabbedPaneQ则有多个常量,用于不同的部分?BR>  
  我徏议?zhn)在更熟(zhn)?Synth 格式q且能够讄 XML 中的l承模型之前Q用每个组件一U式Pone-style-per-componentQ的讄。这U结构虽然没有利用所?XML 的分层结构功能,但它是最Ҏ(gu)讄、编写代码和调试的?BR>  
  在处?Synth XML 文gӞq有一点很重要Qƈ不是M形式都是合法的。如果有输入错误Q或者在 XML 中用了不正的属性,q些错误只有当外观装载期间抛Z个运行时异常时才能发现。解x法:(x)在将 XML 文g发布l客户之前,对其q行试?BR>  
  Demo 应用E序
  
  我将带?zhn)构徏一个简单的d屏幕Q用它作Z子应用程序,向?zhn)展?Synth XML 文g的工作原理。该屏幕提供了够多的组Ӟ通过q些lgQ可以看?XML 文g的所有重要部分,如果使这些部分结合v来便可以创徏一个完整的外观?BR>  
  通过比较?1 和图 2Q具?Ocean 外观的登录屏q看上去与?zhn)预期的一?—?单,直接Q也令h厌烦。具?Synth 外观的登录屏q则完全不同?BR>  
  
?1. h Ocean 外观?Demo 应用E序
   
  ?2. h Synth 外观?Demo 应用E序
   

  更改颜色和字?/B>
  
  ?demo 应用E序创徏外观的第一步是讄默认颜色和字体。?zhn)?white Aharoni 字体作ؓ(f)每个lg的默认字体,如果没有Ҏ(gu)讄lg的话Q就使用q种字体?BR>  
  (zhn)可以将更改字体?XML 攑֜ <style> 标签内的M地方。还可以颜色嵌入到一?<state> 标签中。在本文的后面部分,我将更详l地讨论 <state> 标签Q但现在只需知道Q一个简单的、不带属性的 <state> </state> 标签可以包含M状态,q个标签正是(zhn)在q里所需要的?BR>  
  color 标签本n需要两个属性:(x)
  
  value 可以?java.awt.Color 帔R的Q?String 表示Q例?RED、BLUEQ,或者,它可以是一U颜色的十六q制表示Q前面加?"#" Q例?#669966Q?BR>  
  type 描述文g应该讄哪个区域的颜艌Ӏ选择?BACKGROUND、FOREGROUND、TEXT_FOREGROUND、TEXT_BACKGROUND ?FOCUS?BR>  
  font 标签有两个必需的属性和一个可选属性。这三个属性直接映到 java.awt.Font cM的三个参敎ͼ(x)
  
  name Q字体的名称Q例如,Verdana、ArialQ?BR>  
  size Q字体大,以像素ؓ(f)单位?BR>  
  style Q如果不使用q个可选标{,那么得到常规外观的字体。其他选项包括 BOLD ?ITALIC。?zhn)q可以通过在这两个属性之间加一个空格来指定_体加斜体的字体QBOLD ITALICQ这U组合属性的技术对?Synth XML 文g中的所有属性都适用Q?BR>  
  最后,通过使用 .* wildcardQ将q个式样l定到应用程序中的每个组Ӟ而不是将其绑定到每个 JLabel 和每个JButton。这个通配W告?Synth 外观为每个组件指定一个默认的 white Aharoni 字体。清?3 展示了用于设|组件字体和颜色的完?XML 代码Q?BR>  
  清单 3. 更改多个lg的字体和颜色
  
  <style id="default">
  <font name="Aharoni" size="14"/>
  <state>
  <color value="#FFFFFF" type="FOREGROUND"/>
  </state></style><bind style="default" type="region" key=".*"/>
  
  使用囑փ
  
  ?2 中的 textfield Ҏ(gu)不是常规外观的单像素矩ŞҎ(gu)。可以用一个图像来创徏q些Ҏ(gu)。这不是我们所熟?zhn)的概?—?囑փ用在 button ?label 中已l有些时候了 —?但?zhn)可以惛_在哪些地方会(x)出问题。如何知道光标移动到什么地方,如何昄文本Q如何创Z同大的文本域?q些问题可以通过囑փ拉Qimage stretchingQ的概念来解冟뀂一个图像文件必Lq应用程序中文本域各个边的长度,因此需要有一U方式来告诉 XML 文g如何适当地拉伸图像,以及(qing)如何处理常规?textfield zdQcarat 和文本控Ӟ?BR>  
  q运的是Q从早期带皮肤的应用E序P有一个方法可用于处理q种cd的拉伸。图像必d?9 个区?—?剙、右上、右部、右下、底部、左下、左部、左上和中间 —?q些区域是通过 XML 文g中的一个属性来指定的。然后呈现程序可以通过一定的方式拉囑փQ以适合指定的空间。图 3 展示了文本域囑փ是如何拉伸的?BR>  
  
?3. ?Synth 中图像如何拉?BR>   

  ?3 中绿色填充区只会(x)垂直拉。也是_(d)当文本域比图像高的时候,q些区域׃(x)变高。当文本域比囑փ长的时候,那些U色填充区只?x)水qx伸。而黄色填充区则是大小固定的。不文本域的大如何,q些区域都会(x)如它们在囑փ文g中那hC。因些区域不?x)拉伸,因此它们应该包含所有画布、特D底艌Ӏ阴影和M一旦拉伸就?x)看h很古怪的东西。最后,中间区域是可选的。?zhn)可以选择d或者忽略该区域。在我们的例子中Q文本域的中间被忽略。此后,呈现E序使用q个区域来处理文本控制和 carat。也是_(d)使用一个图像文件完全画出文本域?BR>  
  imagePainter 标签提供了在外观中用图像所需的所有信息。它只需要几个属性:(x)
  
  path Q所使用的图像的路径?BR>  
  sourceInsets Q按像素计算?insetsQ表C图 3 中绿色区域的宽度和粉U色区域的高度。它们依ơ映到剙、左部、底部和右部?BR>  
  method Q这也许是最令h费解的属性。它直接映射?javax.swing.plaf.synth.SynthPainter cM的一个函数。这个类包含大约 100 个函敎ͼ所有这些函数都?paint 开始。每个函数映到在一?Swing lg中某个特定的l画d。?zhn)只需扑ֈ一个合适的函数Q然后去?paint 字符Ԍq随后的首个字母ؓ(f)写形式Q便可以讄该属性。例如,paintTextFieldBorder ?textFieldBorder 的属性。呈现程序(rendererQ负责剩下的工作?BR>  
  paintCenter Q该属性允许?zhn)保留或者舍弃图像的中间区域Q例如在一个按钮中Q。在q个例子中,textfield 舍弃了中间区域,以便昄文本?BR>  
  使用囑փ画边框的最后一步是加大默认?insetsQ以便处理用来画q些 insets 的图像。如果没有更?insetsQ那么就看不见Q何图像。?zhn)需要添加一?<insets> 标签来增?insetsQ以便在其中d囑փ。在大多数情况下Qinsets 的值应该与在图像中使用?insets 的值相同?BR>  
  清单 4 展示了用于装载图像的 XML 代码。注?sourceInsets 如何保囑փ只有适当的部分被拉?BR>  
  清单 4. 装蝲囑փ
  
  <style id="textfield">
  <opaque value="true"/>
  <state>
  <font name="Aharoni" size="14"/>
  <color value="#D2DFF2" type="BACKGROUND"/>
  <color value="#000000" type="TEXT_FOREGROUND"/>
  </state>  <imagePainter method="textFieldBorder" path="images/textfield.png"
  sourceInsets="4 6 4 6" paintCenter="false"/>
  <insets top="4" left="6" bottom="4" right="6"/></style><bind style="textfield" type="region" key="TextField"/>
  
  处理不同的状?/B>
  
  从前面的例子可以看到Q?lt;state> 标签是定义一个组件的焦点所在。在清单 3 和清?4 中,color ?font 标签都处?<state> 标签内。现在我解?<state> 标签的作用?BR>  
  默认状态是?<state> 标签中没有指定属性,q对于定义文本域?label 中的颜色和字体已l够了Q因两种lg的状态不?x)改变。但是在那些状态会(x)改变的组件中Q例如按钮)Q可以ؓ(f)每种状态定义完全不同的外观。每U状态可以有它自q颜色、字体和囑փ。?zhn)可以比较d屏幕?Cancel 按钮在默认状态(?4Q和 mouse-over 状态(?5Q下的不同?BR>  
  
?4. DEFAULT 状态下?Cancel 按钮
   
  ?5. MOUSE_OVER 状态下?Cancel 按钮
   

  <state> 标签只需要一?value 属性,该属性定义了实际的组件状态。如果没有指?valueQ如清单 3 ?4 所C,那么每种状态都使用默认倹{如果指?value 属性,那么可以选择 ENABLED、MOUSE_OVER、PRESSED、DISABLED、FOCUSED、SELECTED ?DEFAULT。这些选择包含 Swing 中Q何组件所有可能的状态。?zhn)q可以在不同选择间添?and 来组合各U状态。例如,如果(zhn)想在鼠标位于按钮之上以?qing)按钮被按下的时候改变按钮上的字体,那么可以使用状态?MOUSE_OVER and PRESSED?BR>  
  清单 5 展示了用于处?demo 应用E序状态的 XML。注意每U状态是如何定义不同的图像和文本颜色的?BR>  
  清单 5. 处理状?BR>  
  <style id="button">
  <state>
  <imagePainter method="buttonBackground" path="images/button.png"
  sourceInsets="9 10 9 12" paintCenter="true" stretch="true"/>
  <insets top="9" left="10" bottom="9" right="12"/>
  <font name="Aharoni" size="16"/>
  <color type="TEXT_FOREGROUND" value="#FFFFFF"/>
  </state>  <state value="MOUSE_OVER">
  <imagePainter method="buttonBackground" path="images/button_on.png"
  sourceInsets="9 10 9 12" paintCenter="true" stretch="true"/>
  <insets top="9" left="10" bottom="9" right="12"/>
  <color type="TEXT_FOREGROUND" value="#FFFFFF"/>
  </state>
  <state value="PRESSED">
  <imagePainter method="buttonBackground" path="images/button_press.png"
  sourceInsets="10 12 8 9" paintCenter="true" stretch="true"/>
  <insets top="10" left="12" bottom="8" right="9"/>
  <color type="TEXT_FOREGROUND" value="#FFFFFF"/>
  </state>  <property key="Button.margin" type="insets" value="0 0 0 0"/></style><bind style="button" type="region" key="Button"/>
  
  处理 <state> 标签的一个重要方面是知道哪些lg有哪些状态。显Ӟ在这个例子中Q按钮可以拥有默认状态、鼠标?zhn)停(mouse-overQ状态和被按下(pressedQ?状态。对于这个例子,q可以定义一个聚焦(focusedQ和用QdisabledQ状态。但是对于一个面板,选中QselectedQ状态根本不适用Q当鼠标处于面板之上时如果改变面板的状态,那么只能招来抱怨?BR>  
  处理特定于组件的属?/B>
  
  定义Ҏ(gu)U组仉通用?XML 属性时QL忽略了一些特定于lg的属性。例?list 的行高、单选钮的图标和菜单的箭头图标,q些都是特定于组件的属性。可以定义的特定于组件的属性有 100 多种Q但是ؓ(f)每个q样的属性定义一?XML 属性就有些q分了。因此,Synth XML 文g允许讄特定于组件的属性?lt;property> 标签像一?HashtableQ它定义一个键/值对来设|属性?BR>  
  d屏幕CZ的复选框演示了如何ؓ(f)特定于组件的属性编写代码。通过定义 imageIconQ可以设|默认状态和选中状态下?CheckBox.icon。这像是翻?100 个属性找到?zhn)惌的属性那L(fng)单?BR>  
  清单 6 展示了ؓ(f)d屏幕中特定于lg的属性编写代码的 XML。注意要首先定义 imageIcon。然后,通过使用囑փ图标?IDQ可以ؓ(f)复选框的每U状态设|一个图标?BR>  
  清单 6. 定义特定于组件的属?BR>  
  <style id="checkbox">
  <imageIcon id="check_off" path="images/checkbox_off.png"/>
  <imageIcon id="check_on" path="images/checkbox_on.png"/>
  <property key="CheckBox.icon" value="check_off"/>
  <state value="SELECTED">
  <property key="CheckBox.icon" value="check_on"/>
  </state></style><bind style="checkbox" type="region" key="Checkbox"/>
  
  使用定制 painter
  
  定义?2 中登录屏q例子的最后工作是用曲U绘制渐变背景。用 XML 来实现这U背景似乎有些别扭,坦白地说Q真是这栗但q样我便有机?x)展C?SynthQ不限制(zhn)在 UI 设计中只使用囑փ和简单的颜色。?zhn)可以使用它来MQ何东ѝ?BR>  
  Synth 允许重写?paint Ҏ(gu)Q即?javax.swing.plaf.synth.SynthPainter cM的方法)Q该Ҏ(gu)l承?SynthPainterQ它?yu)覆盖那些(zhn)惌定制l画方式的特定函数。在q个例子中,需要定?paintPanelBackground Ҏ(gu)Q因U设计不能以 Synth XML 格式描述?BR>  
  Z使用定制?painterQ或者在 XML 中以M方式创徏一个类Q可以?<object> 标签?lt;object> 标签允许创徏和保持用于I?Synth 呈现E序的Q?Java cR?lt;object> 标签带有两个元素Q?BR>  
  class Q将创徏的类的全名?BR>  
  id Q用于在 XML 文档中引用这个类实例?ID 名?BR>  
  通过使用对象Q不仅可以创?BackgroundPainter cȝ实例 —?q个cd用于l制背景Q而且q可以创?ColorUIResource cȝ实例Q在q个cM可以定义背景颜色。想一惻I(x)?BackgroundPainter cM定义背景中用的颜色Q这?Synth 的目标是矛盾的,Synth 的目标是在一个外?XML 文g中定义一切,而不是在一?Java 文g中进行硬~码?BR>  
  使用定制 painter 的最后一步是告诉 Synth 呈现引擎Q是(zhn)自p不?SynthPainter cL提供函数。在q个例子中,首先?BackgroundPainter cM定义 paintPanelBackground 函数Qƈ?SynthPainter cd义剩下的l画函数?lt;painter> 标签让?zhn)可以覆?SynthPainter 函数。它带有两个元素Q?BR>  
  method Q定?painter 应该覆盖的方法。从 使用囑փ 一节中(zhn)已l得知,(zhn)可以在 javax.swing.plaf.synth.SynthPainter cM扑ֈq些函数Q但是应该删除每个函数开始部分的 paint 字符Ԍ例如QSynthPainter 中的 paintPanelBackground ?XML 文g中应该是 panelBackgroundQ?BR>  
  idQ对覆盖此Ҏ(gu)的类的引用?BR>  
  Z在定?painter 中用颜Ԍ必须颜色保存在 javax.swing.UIDefaults cM。在清单 7 和清?8 中可以看刎ͼ颜色保存在 UIDefaults 中十分简单,对于那些接触q?UI 创徏的h来说应该Q应该比较熟(zhn)这些内宏V在 XML 文g中定义的键将成ؓ(f) UIManager 中的引用Q在 BackgroundPainter ?Java 代码中,可以使用 UIManager 来获得颜艌Ӏ?BR>  
  清单 7 展示了在例子应用E序中用定?painter ?XML 代码。注意必首先定义颜艌Ӏ?BR>  
  清单 7. 使用定制 painter
  
  <style id="panel">
  <object id="background" class="demo.synth.BackgroundPainter"/>
  <object class="javax.swing.plaf.ColorUIResource" id="startColor">
  <int>30</int>
  <int>123</int>
  <int>235</int>
  </object>
  <defaultsProperty key="Panel.startBackground" type="idref" value="startColor"/>
  <object class="javax.swing.plaf.ColorUIResource" id="endColor">
  <int>1</int>
  <int>20</int>
  <int>80</int>
  </object>
  <defaultsProperty key="Panel.endBackground" type="idref" value="endColor"/>
  <painter method="panelBackground" idref="background"/></style><bind style="panel" type="region" key="Panel"/>
  
  清单 8 展示了例子应用程序的定制l画cȝ Java 代码Q?BR>  
  清单 8. 定制l画?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);
  
  }}
  
  更高U的讄
  
  本节包含两个出d屏幕例子范围的技术。在创徏(zhn)自q Synth 外观Ӟ(zhn)可能发现这两项技术很有用?BR>  
  l制?Swing lg
  
  可以改变每个 Swing lg的外观这一点虽然很,但是q应该能够改变其他组?—?开发h员创建的用于填补 Swing I缺的组?—?的外观。在q种情况下,<bind> 标签需要作出改变,以反映正在绘制的不是一?Swing lg。type 属性可以有两种|(x)如果映射C?Swing lgQ则该gؓ(f) regionQ如果映到?Swing lgQ则该gؓ(f) name。因此,如果?<bind> 标签变ؓ(f) <bind style="mystyle" type="name" key="Custom.*"/>Q则?x)改变每个类名?Custom 开始的lgQ例如,CustomTextField ?CustomLabelQ,使它们?mystyle 式样?BR>  
  式样的分层结?/B>
  
  除了在创?XML 文g时?KISS 式样之外Q还可以构徏分层ơ的一些式Pq将q些式样应用于组件中。清?9 应该可以清楚地演C一炏V注意,Synth 使用最后定义的属性来昄lg?BR>  
  清单 9. 分层l构的例?BR>  
  <style id="base">
  <color value="BLACK" type="BACKGROUND"/>
  <state>
  <font size="14"/>
  </state>
  </style>
  <bind style="base" type="region" key=".*"/>
  <style id="sublevel" clone="base">
  <color value="RED" type="BACKGROUND"/>
  </style>
  <bind style="sublevel" type="region" key="Label"/>
  
  清单 9 中的代码使每个组件有一个黑色的背景Q字体大ؓ(f) 14Q但 label lg除外Qlabel lg拥有U色的背景。通过克隆 sublevel 中的 base 式样Q清?9 复制了整个式栗然后,(zhn)可以覆盖所需的Q何特定属性?BR>  
  ?Synth 的性能、可靠性和效率
  
  xQ?zhn)已经看到如何创徏用?Synth ?XML 文gQ以?qing)如何通过更改字体、更攚w色和d囑փ来创建定制的外观Q但对于 Synth 可能q有些疑问。如果?zhn)使?Swing 已经有一D|_(d)那么我可以肯定,(zhn)首先想到的是性能问题。我设计了一些性能试Q这些测试表明,Synth 不会(x)令?zhn)?UI 慢如蜗牛。ؓ(f)了调查?zhn)可能看到的问题(q讨论我在?Synth 时已l碰到过的一些问题)Q我查看?Java Bug Parade Q请参阅 参考资料)。最后,我将回答最重要的问?—?Synth 真的可以节省(zhn)的旉吗?
  
  装蝲那么多图像会(x)不会(x)?Synth 变得更慢Q?/B>
  
  Z回答q个问题Q我创徏了两个测试,q让(zhn)更深切C?Synth 在性能斚w与其他外观的比较。第一个测试将试CZd应用E序的装载时间。该试装蝲 6 ?Synth 囑փQƈ这个装载时间与一个开发h员可能创建的一般屏q的装蝲旉q行比较。第二个试是关于装载时间的压力试 —?一个中有 100 多个lg?BR>  
  两个试都将试 Ocean ?Motif 外观的装载时_(d)以便q行比较。ؓ(f)了公正v见,我在三种机器上运行了q两个测?—?一U是安装 Windows XP 的手提电(sh)脑,一U是 SuSE Linux boxQ还有一U是 Red Hat Linux box。结果显C在?1 和表 2 中?BR>  
  ?1. d屏幕的^均装载时?BR>  
  机器配置 Ocean Motif Synth
  Windows XP - 1.7GHz - 2GB RAM .32 seconds .29 seconds .57 seconds
  SuSE Linux 9.0 - 3.3GHz - 2GB RAM .23 seconds .20 seconds .45 seconds
  Red Hat Linux 3.0 - 1.4GHz - 512MB RAM .37 seconds .32 seconds .61 seconds
  
  ?2. 包含 100 个组件的屏幕的^均装载时?BR>  
  机器配置 Ocean Motif Synth
  Windows XP - 1.7GHz - 2GB RAM .33 seconds .32 seconds .34 seconds
  SuSE Linux 9.0 - 3.3GHz - 2GB RAM .23 seconds .23 seconds .30 seconds
  Red Hat Linux 3.0 - 1.4GHz - 512MB RAM .40 seconds .40 seconds .43 seconds
  
  (zhn)可以看刎ͼSynth 外观的装载时间只?Ocean ?Motif 慢一点点。但是请注意Q登录屏q与压力试?x)比装蝲更慢一些。乍一看来Q这g很奇怪,但如果仔l研IӞ便可以发现v因。压力测试没有装载复选框中所使用的图像,而登录屏q却装蝲了这些图像。据此可以下l论Q在 Synth 外观中用的每个附加囑փ增加了装载时间。与含有两个使用两种不同囑փ的组件的应用E序相比Q用相同图像的 100 个组件装载v来要更快一些。减所使用囑փ的数量可以提?Synth 装蝲旉斚w的性能?BR>  
  Synth 是不是像 Swing 一P在第一ơ发布时满是 bugQ?/B>
  
  Ҏ(gu) Sun Java 开发者网站上 Bug Parade 的评判,Synth 看上L一个比较干净、没?bug 的品。然而,没有哪个软g是完的。Synth 曄?125 ?bugQ这?Synth 处理 JTabbedPane 的方式不成比例。因此,如果(zhn)经历到一些问题,不要感到惊讶。然而,Ҏ(gu) Sun 的辩护,q些~陷都处于“关闭(ClosedQ”状态。但通常的情冉|Q如果以前存在某些问题,那么q些问题在将来也很可能会(x)出现?BR>  
  虽然 bug 数据库ؓ(f) Synth 赋予了一个相对干净的Ş象,我在处理d屏幕的时候还是碰C些问题。我W一ơ尝试更?JPanel 背景颜色旉到失败。我创徏了一个特定于 JPanel 的式Pq将其绑定到所?JPanelQ但q样行不通。而当我决定用自q定制 painter Ӟ事情p决了?BR>  
  一个更大的问题是当状态改变时对组件进行重新绘制。在处理按钮?qing)其状态时Q我发现Q按钮上的文本不能正地改变颜色。当初始化时Q作为默认颜色的白色没有如期昄Qƈ且直到触发了状态变化之后才出现Q然后就被重新设|ؓ(f)默认颜色。如果仔l研I关?Synth 的文档,可以发现这个小qQQ“虽然可以ؓ(f)每种状态提供不同的字体Q但在一般情况下Q当lg的状态变化时Q组件不?x)重新生效,所以,如果(zhn)试图ؓ(f)不同状态用有明显不同大小的字体时Q有可能?x)遇到字体大的问题”。听hg它们遇上了试图让 Synth 使用老的 Swing 代码的问题。因此,如果要在状态改变时更改字体Q那么要心?BR>  
  Synth 看上ȝ很有 bug。但如果随处出点问题,那些本应该行得通的代码׃(x)行不通,我不?x)对此感到惊讶。不q,变通的办法不难扑ֈ。对于在工作中碰到的每个问题Q我总能扑ֈ一个变通的办法?BR>  
  利用 Synth 可以创徏出完全专业的外观吗?
  
  回答是肯定的。Java 1.4 中发布的 GTK+ ?Windows XP 外观完全是?Synth 创徏的。(那时它不是一个已公布?API。) 所以这斚w昄没有问题?BR>  
  ?Synth 创徏一个完整的外观比用 Java 代码~写q样的外观要快多?
  
  q很Ҏ(gu)计算。这两种Ҏ(gu)各自都包含两个步骤:(x)
  
  创徏外观Q这通常是由囑Ş设计人员负责的工作?BR>  
  图形界面{化成代码?BR>  
  不管是用 Java ~写代码q是使用 SynthQ图形界面设计这部分工作所q旉是相同的。根据我创徏定制外观的经验,我估计ؓ(f)一个应用程序创Z个完整的外观需要两个图形设计h员两周的旉。也是_(d)囑փ设计工作需?4 Z周(person-weekQ的人力?BR>  
  通常Q根据我的经验,通过cȝ承的方式图形界面翻译成立即可用的外观需要三?Java ~程人员花大U两个月的时间。也是_(d)~写 Java 代码需?6 个h一个月Qperson-monthQ的人力。加上图形界面设计工作,通过重写 UI c,?Swing 创徏一个完全定制的外观d需?7 个h一个月的工作量。这些数据有助于(zhn)明白ؓ(f)什?Internet 上可供下载的定制外观是那么少?BR>  
  通过图形界面{换成一?XML 文gQSynth 可以节省大量的时间。通过 Java ~程创徏外观需?6 个h一个月的工作量Q而一个开发h员将囑Ş界面转换?Synth XML 文g只需两个星期。用 Synth 创徏完整外观所需的工作量减少C?6 个h一周的工作?—?通过使用 Synth 节省了超q?5 个月的时间。对于一个由两个囑Ş设计师和两个E序员组成的团队Q在短短三个星期内便可以创徏Z个完整的 Synth 外观?BR>  
  l束?/B>
  
  Synth 皮肤的概念引入?Swing 中。相对于传统的用 Java 代码~写定制外观的方法,Synth 最大的优势是节省时间。一个完整的 Swing 外观可以在不C个月的时间里完成Q这比用 Java 语言~程的方法要?5 倍。对于有q劲的开发h员,在用 Java 代码~写一个外观的旉里,他可以创?5 ?Synth 外观?BR>  
  然而,Synth q毫无瑕疵。通过~写 Java 代码覆盖 Swing 外观Q可以同时改变应用程序的外观和感?。?Synth 只允许改变应用程序的外观。这是一个很大的不同之处。外观是指应用程序中使用的颜艌Ӏ字体和囑Ş。另一斚wQ感觉则对应于应用程序在交互期间展现出来的行?—?q里指单M下鼠标右键,那里按下一个键。例如,如果(zhn)想改变一?JList 的行为,希望通过单击鼠标左键选中条目Q然后再通过单击鼠标右键来删除条目,那么?Synth 是无法做到这些的。?zhn)需要ؓ(f)新的外观~写 Java 代码。Synth 实际上应该称ZU新?Swing 外观Q而不是一U普通外观。通过 Synth 可以快速改?UI 的外观,?UI 的感觉永q都是默认的 Swing 感觉?BR>  
  当然Q如果?zhn)想通过为应用程序提供新的外观来使之整洁漂亮Q或者(f)望看到比令h讨厌?Metal 外观Q谢天谢圎ͼ?Java 5.0 中它已成为历Ԍ更好?Swing 应用E序外观Q那?Synth 是很好的一个选择。它不存在性能问题Qƈ且看上去 bug 也很。Sun 已经表示Q通过发布 GTK+ 外观Q用 Synth 可以创徏完整的外观?BR>  
  令h吃惊的是QSynth 文档和实例现在还很少。阅L文之后,对于 Synth 的工作原理?zhn)应该有一个更q理解Qƈ且能够用一个组件一个样式标{(one-style-tag-per-one-componentQ的设计来生成一个完整的 Synth XML 文档。Synth 的承和分层模型为创?style 标签提供了更强大的方法,但没有它们仍然可以创建完整的外观。理x冉|Q随着?Synth 认识的加深,Swing UI C֌出现皮肤数量的大爆炸。有了数百个可供选择的外观,通常那些加在 Swing 应用E序w上的“长相恐怖”、“丑陋”之cȝ责骂之词也将永远消失?img src ="http://www.tkk7.com/pateric/aggbug/27682.html" width = "1" height = "1" />

pateric 2006-01-12 10:38 发表评论
]]>
Synthhttp://www.tkk7.com/pateric/articles/27675.htmlpatericpatericThu, 12 Jan 2006 02:25:00 GMThttp://www.tkk7.com/pateric/articles/27675.htmlhttp://www.tkk7.com/pateric/comments/27675.htmlhttp://www.tkk7.com/pateric/articles/27675.html#Feedback0http://www.tkk7.com/pateric/comments/commentRss/27675.htmlhttp://www.tkk7.com/pateric/services/trackbacks/27675.html下面是一个简单的例子Q?--来自sun java技术论?
   import java.awt.BorderLayout;
   import java.awt.EventQueue;
   import java.io.InputStream;
   import java.text.ParseException;
   import javax.swing.JButton;
   import javax.swing.JLabel;
   import javax.swing.JFrame;
   import static javax.swing.JFrame.*;
   import javax.swing.UIManager;
   import javax.swing.plaf.synth.SynthLookAndFeel;

   public class HelloSynth {
     public static void main(String args[]) {
       Runnable runner = new Runnable() {
         public void run() {
           SynthLookAndFeel synth = new SynthLookAndFeel();
           try {
             Class aClass = HelloSynth.class;
             InputStream is = 
                aClass.getResourceAsStream("synth.xml");
             if (is == null) {
               System.err.println("Missing configuration file");
               System.exit(-1);
             }
             synth.load(is, aClass);
           } catch (ParseException e) {
             System.err.println("Bad configuration file");
             System.exit(-2);
           }
           try {
             UIManager.setLookAndFeel(synth);
           } catch 
              (javax.swing.UnsupportedLookAndFeelException e) {
             System.err.println("Cannot change to Synth");
             System.exit(-3);
           }
           JFrame frame = new JFrame("First");
           frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
           JLabel label = new JLabel("Hello, Synth");
           label.setHorizontalAlignment(JLabel.CENTER);
           frame.add(label);
           frame.setSize(300, 100);
           frame.setVisible(true);
         }
       };
       EventQueue.invokeLater(runner);
     }
   }
HelloSynth 创徏了一个新的SynthLookAndFeel的对象ƈ用load办法dxml文gQsynth.xml。注意synth.load(InputStream,Class) 的两个参敎ͼInputStream不用q一步讲解,是dxml文g的数据流QClass是数据来源类Q这里当然是HelloSynth的instance: aClass.
下面是synth.xml

HelloSynthdsynth.xmlQ创Z个JLabel,然后把它输出到屏q。可以看到JLabel的颜Ԍ字体都是通过xml文g来设|的?BR>具体如下Q?BR>18-point bold-italic font,
opaque,
foreground colorQpink (text color)Q?BR>background colorQyellow
输出Q?BR>
下面是另一?xml的例子:(x)
输出Q?BR> 关于Synth所应用到的xml的格式和语法 请参考:(x)
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/synth/doc-files/synthFileFormat.html
关于Swinglg的属性参?请参考:(x)
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/plaf/synth/doc-files/componentProperties.html 参考链接里面的例子
甚至lg的状?-一般以往用到actionListener的地? 囑Şicon的\径,对象参数的嵌?主要是Painter的?{等都可?
用xml文g来控制从而减繁冗的代码~写?_

pateric 2006-01-12 10:25 发表评论
]]>
վ֩ģ壺 պһ| ޹Ʒר| ޳aƬ߲| ߹ۿhƬ| һ| 91ɫۺϾþѷ| ɫþAVۺ| þþþƷ2019ѹۿ| þAV| 91Ƶ91| ĻƷ| ѿƬִֻ| þþþ޹AV鶹 | AVר4SE| þþƷվ| AvרDVD| ߹ۿwwwձվ| ҹɼӰԺ| ѹۿһëƬ| պƷƵ| avһ| ĻmvߵӰ| һ91| ߹ۿƵ| һؼŮ18ëƬƵ| ޳AVƬ߹ۿww| 91Ʒѹۿ| պƬӰ| ۺҹ | 37pao˹Ƶ| ޹a˾Ʒ| һA| 99REþþƷﶼǾƷ| ޾ƷƵ߹ۿƵ| պһƵѹۿ| һƷһAVһ| ۺһ| Ҹ鶹| èԴ߹ۿ| ˬˬƬA| Դ߹ۿ|