技术开发 频道

JDK 7探秘三:用JLayer装饰Swing组件

  【IT168 文档】JDK 7引入了一个新的Swing组件来装饰其它Swing组件,这个新的组件是通过javax.swing.JLayer类,基于Swing实验室项目Swing Helper的JXLayer实现的。JLayer结合javax.swing.plaf.LayerUI使用可以实现高级的绘制效果,并可以在它的边界范围内接收由java.awt.AWTEvents产生的所有通知。本文将为大家一一介绍这些类。

  JLayer和LayerUI概述

  根据JDK的文档描述,JLayer委托处理LayerUI对象的绘制和输入事件,LayerUI负责装饰,你可以使用这些类修改现有组件的外观和行为使它们的装饰效果更好。

  实际上,你可以自己动手扩展LayerUI,废除它们自带的方法,自己定制绘制和事件处理方法,然后将这个类的实例和装饰后的组件一道,传递给下面的JLayer构造器:

public JLayer(V view,LayerUI<V> ui)

  第一个参数可以是任何类的延伸java.awt.Component,表示你要装饰的Swing组件,这个组件可以是一个JPanel或其它容器,这个容器和它里面所有的组件都将被装饰,第二个参数代表装饰器。使用这些构造器创建JLayer时,可以延迟指定LayerUI实例和/或视图。

  如果初始化时不指定视图,之后你可以调用JLayer's public void setView(V view)方法来提供一个视图,这个类也提供了一个public V getView()方法返回组件是否被装饰,没有装饰就返回null。

  如果初始化时不指定LayerUI实例,之后你可以调用JLayer's public void setUI(LayerUI ui方法提供一个实例,这个类也提供了一个public LayerUI getUI()方法返回当前的装饰器,没有装饰器就返回null。

  JLayer自定义绘制

  为了演示JLayer的自定义绘制特性,我创建了一个ReverseText程序,其代码显示在清单1中,当按下按钮时,输入到textfield中的文本将全部颠倒,这个程序使用JLayer在用户界面后绘制了一个墙纸图案。

  清单1. ReverseText.java

// ReverseText.java
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayer;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.plaf.LayerUI;
public class ReverseText
{
  
private static Color PALE_YELLOW = new Color (1.0f1.0f0.0f0.2f);
  
private static Color PALE_GREEN = new Color (0.0f1.0f0.0f0.2f);
  
private static JLayer<JPanel> createLayer ()
   {
      LayerUI
<JPanel> layerUI;
      layerUI
= new LayerUI<JPanel> ()
      {
        
public void paint (Graphics g,JComponent c)
         {
            
// Paint the wallpaper.
            Graphics2D g2 = (Graphics2D) g;
            g2.setPaint (
new GradientPaint (00,PALE_YELLOW,
                                            
50,PALE_GREEN,true));
            g2.fillRect (
00,c.getWidth (),c.getHeight ());
            
// Make sure that layer's panel view is not opaque.
            JLayer l = (JLayer) c;
            
if (l.getView ().isOpaque ())
                ((JPanel) l.getView ()).setOpaque (
false);
            
// Paint the view minus its background.
            super.paint (g,c);
         }
      };
      
// Create a user interface to be decorated.
      JPanel pnl = new JPanel ();
      JLabel lblName
= new JLabel ("Name:");
      pnl.add (lblName);
      
final JTextField txtName = new JTextField (20);
      pnl.add (txtName);
      JButton btnReverse
= new JButton ("Reverse");
      pnl.add (btnReverse);
      ActionListener al;
      al
= new ActionListener ()
           {
              
public void actionPerformed (ActionEvent ae)
               {
                  String txt
= txtName.getText ();
                  txt
= new StringBuffer (txt).reverse ().toString ();
                  txtName.setText (txt);
               }
           };
      btnReverse.addActionListener (al);
      
// Create the layer for the panel using our custom layerUI.
      return new JLayer<JPanel> (pnl,layerUI);
   }
  
private static void createAndShowUI ()
   {
      JFrame frame
= new JFrame ("Reverse Text");
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.add (createLayer ());
      frame.pack ();
      frame.setLocationRelativeTo (
null);
      frame.setVisible (
true);
   }
  
public static void main (String [] args)
   {
      Runnable r
= new Runnable ()
                   {
                      
public void run ()
                       {
                          createAndShowUI ();
                       }
                   };
      EventQueue.invokeLater (r);
   }
}
0