1、jlayerJLayer和LayerUI概述根据JDK的文档描述,JLayer委托处理LayerUI对象的绘制和输入事件,LayerUI负责装饰,你可以使用这些类修改现有组件的外观和行为使它们的装饰效果更好。实际上,你可以自己动手扩展LayerUI,废除它们自带的方法,自己定制绘制和事件处理方法,然后将这个类的实例和装饰后的组件一道,传递给下面的JLayer构造器:public JLayer(V view,LayerUI ui)第一个参数可以是任何类的延伸java.awt.Component,表示你要装饰的Swing组件,这个组件可以是一个JPanel或其它容器,这个容器和它里面所有的组件都将
2、被装饰,第二个参数代表装饰器。使用这些构造器创建JLayer时,可以延迟指定LayerUI实例和/或视图。如果初始化时不指定视图,之后你可以调用JLayers public void setView(V view)方法来提供一个视图,这个类也提供了一个public V getView()方法返回组件是否被装饰,没有装饰就返回null。如果初始化时不指定LayerUI实例,之后你可以调用JLayers public void setUI(LayerUI ui方法提供一个实例,这个类也提供了一个public LayerUI getUI()方法返回当前的装饰器,没有装饰器就返回null。JLayer
3、自定义绘制为了演示JLayer的自定义绘制特性,我创建了一个ReverseText程序,其代码显示在清单1中,当按下按钮时,输入到textfield中的文本将全部颠倒,这个程序使用JLayer在用户界面后绘制了一个墙纸图案。清单1. ReverseText.java1./ ReverseText.java2.import java.awt.Color;3.import java.awt.EventQueue;4.import java.awt.GradientPaint;5.import java.awt.Graphics;6.import java.awt.Graphics2D;7.impo
4、rt java.awt.event.ActionEvent;8.import java.awt.event.ActionListener;9.import javax.swing.JButton;10.import javax.swing.JComponent;11.import javax.swing.JFrame;12.import javax.swing.JLabel;13.import javax.swing.JLayer;14.import javax.swing.JPanel;15.import javax.swing.JTextField;16.import javax.swin
5、g.plaf.LayerUI;17.public class ReverseText18.19. private static Color PALE_YELLOW = new Color (1.0f,1.0f,0.0f,0.2f);20. private static Color PALE_GREEN = new Color (0.0f,1.0f,0.0f,0.2f);21. private static JLayer createLayer ()22. 23. LayerUI layerUI;24. layerUI = new LayerUI ()25. 26. public void pa
6、int (Graphics g,JComponent c)27. 28. / Paint the wallpaper.29. Graphics2D g2 = (Graphics2D) g;30. g2.setPaint (new GradientPaint (0,0,PALE_YELLOW,31. 5,0,PALE_GREEN,true);32. g2.fillRect (0,0,c.getWidth (),c.getHeight ();33. / Make sure that layers panel view is not opaque.34. JLayer l = (JLayer) c;
7、35. if (l.getView ().isOpaque ()36. (JPanel) l.getView ().setOpaque (false);37. / Paint the view minus its background.38. super.paint (g,c);39. 40. ;41. / Create a user interface to be decorated.42. JPanel pnl = new JPanel ();43. JLabel lblName = new JLabel (Name:);44. pnl.add (lblName);45. final JT
8、extField txtName = new JTextField (20);46. pnl.add (txtName);47. JButton btnReverse = new JButton (Reverse);48. pnl.add (btnReverse);49. ActionListener al;50. al = new ActionListener ()51. 52. public void actionPerformed (ActionEvent ae)53. 54. String txt = txtName.getText ();55. txt = new StringBuf
9、fer (txt).reverse ().toString ();56. txtName.setText (txt);57. 58. ;59. btnReverse.addActionListener (al);60. / Create the layer for the panel using our custom layerUI.61. return new JLayer (pnl,layerUI);62. 63. private static void createAndShowUI ()64. 65. JFrame frame = new JFrame (Reverse Text);6
10、6. frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);67. frame.add (createLayer ();68. frame.pack ();69. frame.setLocationRelativeTo (null);70. frame.setVisible (true);71. 72. public static void main (String args)73. 74. Runnable r = new Runnable ()75. 76. public void run ()77. 78. createAndShow
11、UI ();79. 80. ;81. EventQueue.invokeLater (r);82. 83.其中createLayer()方法是最重要的代码,它创建了一个匿名LayerUI子类的实例,绘制了墙纸和JPanel视图,创建了UI,在实例中包含了UI的面板容器。绘制操作是由LayerUIs public void paint(Graphics g,JComponent c)方法实现的,第二个参数引用了视图(被装饰的组件)中的JLayer实例,不是引用的视图。在视图后创建了渐变渲染墙纸后,调用paint()方法确保视图(没有嵌套面板的单一面板)是透明的,它将会隐藏墙纸,然后绘制视图。pa
12、int()对比paintLayer()JDK文档中除了提到paint()方法外,还提到了paintLayer()方法,我这里之所以选择paint()方法,是因为 LayerUI中不存在paintLayer(),此外,文档还错误地引用paintLayer() doesnt exist in LayerUI. Furthermore,the documentation incorrectly refers to addPropertyChange(),configureGraphics(),processComponentEvent(), processFocusEvent(),processHi
13、erarchyBoundsEvent(),processHierarchyEvent (),processKeyEvent(),processMouseEvent(),processMouseMotionEvent(), processMouseWheelEvent(),and repaintLayer()这些在LayerUI中根本不存在的方法,当然这些方法也可能在JDK 7最终发布时会包含进来。ReverseText程序演示了自定义绘制,避开了事件触发,不需要检测事件,因为程序只关心墙纸的绘制效果。相反,清单2显示了一个需要响应鼠标移动事件的程序代码。清单2. BrandedUI.java1
14、./ BrandedUI.java2.import java.awt.AWTEvent;3.import java.awt.Color;4.import java.awt.Component;5.import java.awt.EventQueue;6.import java.awt.Font;7.import java.awt.GradientPaint;8.import java.awt.Graphics;9.import java.awt.Graphics2D;10.import java.awt.GridLayout;11.import java.awt.Point;12.import
15、 java.awt.event.MouseEvent;13.import javax.swing.JComponent;14.import javax.swing.JFrame;15.import javax.swing.JLabel;16.import javax.swing.JLayer;17.import javax.swing.JPanel;18.import javax.swing.JTextField;19.import javax.swing.SwingUtilities;20.import javax.swing.plaf.LayerUI;21.public class Bra
16、ndedUI22.23. private static Color PALE_BLUE = new Color (0.0f, 0.0f, 1.0f, 0.3f);24. private static Color PALE_RED = new Color (1.0f, 0.0f, 0.0f, 0.3f);25. private static Font BRAND_FONT = new Font (Arial, Font.BOLD, 18);26. private static String MSG = My brand;27. private static JLayer createLayer
17、()28. 29. LayerUI layerUI;30. layerUI = new LayerUI ()31. 32. private Color color = PALE_BLUE;33. public void installUI (JComponent c)34. 35. super.installUI (c);36. (JLayer) c).setLayerEventMask (AWTEvent.MOUSE_MOTION_EVENT_MASK);37. 38. public void eventDispatched (AWTEvent e,39. JLayer l)40. 41.
18、MouseEvent me = (MouseEvent) e;42. Point pt = SwingUtilities.convertPoint (Component) me.getSource (),43. me.getX (), me.getY (), l);44. int cx = l.getWidth ()/2;45. int cy = l.getHeight ()/2;46. if (pt.x cx-45 & pt.x cy-10 & pt.y cy+10)47. color = PALE_RED;48. else49. color = PALE_BLUE;50. l.repain
19、t ();51. 52. public void paint (Graphics g, JComponent c)53. 54. / Paint the view.55. super.paint (g, c);56. / Paint the brand.57. g.setColor (color);58. g.setFont (BRAND_FONT);59. int width = g.getFontMetrics ().stringWidth (MSG);60. int height = g.getFontMetrics ().getHeight ();61. g.drawString (M
20、SG, (c.getWidth ()-width)/2,62. c.getHeight ()/2+height/4);63. 64. public void uninstallUI (JComponent c)65. 66. super.uninstallUI (c);67. (JLayer) c).setLayerEventMask (0);68. 69. ;70. / Create a user interface to be decorated.71. JPanel pnlMain = new JPanel ();72. pnlMain.setLayout (new GridLayout
21、 (2, 1);73. JPanel pnlTemp = new JPanel ();74. JLabel lblName = new JLabel (Name:);75. pnlTemp.add (lblName);76. JTextField txtName = new JTextField (20);77. pnlTemp.add (txtName);78. pnlMain.add (pnlTemp);79. pnlTemp = new JPanel ();80. JLabel lblAddr = new JLabel (Address:);81. pnlTemp.add (lblAdd
22、r);82. JTextField txtAddr = new JTextField (20);83. pnlTemp.add (txtAddr);84. pnlMain.add (pnlTemp);85. / Create the layer for the main panel using our custom layerUI.86. return new JLayer (pnlMain, layerUI);87. 88. private static void createAndShowUI ()89. 90. JFrame frame = new JFrame (Branded UI)
23、;91. frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);92. frame.add (createLayer ();93. frame.pack ();94. frame.setLocationRelativeTo (null);95. frame.setVisible (true);96. 97. public static void main (String args)98. 99. Runnable r = new Runnable ()100. 101. public void run ()102. 103. createA
24、ndShowUI ();104. 105. ;106. EventQueue.invokeLater (r);107. 108.上面的代码渲染UI上的文本印记,我们通常使用印记提醒用户使用的是试用软件,印记文本是半透明的,以便背景可以全部显示,我们不希望这个印记给用户造成太大的干扰。另一方面,我们希望用户能注意到这个印记,让他们下定决心购买这款软件,清单2中的代码通过改变印记的颜色(改成淡红色)来达到这个目的,当鼠标移到初始值是绿色的印记面板上时,颜色就变成淡红色。事件检测JLayer和LayerUI结合起来可以检测视图任意区域上发生的事件(包括嵌套的子组件),这些类共同提供了4个方法来检测事
25、件。 public void setLayerEventMask(long layerEventMask)调用这个JLayer方法时必须使用位掩码AWTEvent常量选择它检测到的事件类型,如:setLayerEventMask (AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);可以检测到按键和焦点改变事件。public void installUI(JComponent c)这个LayerUI方法通常放在setLayerEventMask()方法之前,这个方法类的代码首先调用超类方法 (super.installUI (c);),然后
26、是引用JLayer的JComponent参数,最后使用setLayerEventMask(): (JLayer) c).setLayerEventMask(AWTEvent.KEY_EVENT_MASK);返回的结果。public void uninstallUI(JComponent c)这个LayerUI方法放在没有参数的setLayerEventMask()方法后,这个方法内的代码首先调用超类方法 (super.uninstallUI (c);),然后是引用JLayer的JComponent参数,最后使用setLayerEventMask(): (JLayer) c).setLayerEventM
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2