Java7的一个新类JLayer:装饰的Swing组件

开发 后端
Java7中的一个新的类,JLayer,也已被添加到提高的Java Swing的能力。 JLayer主要用于装饰的Swing组件。你可以用它改变如何绘制组件,以及它们如何响应事件。

Java7中的一个新的类,JLayer,也已被添加到提高的Java Swing的能力。 JLayer主要用于装饰的Swing组件。你可以用它改变如何绘制组件,以及它们如何响应事件。

下面是这个类的一个简单的例子:

先看运行结果:

1、鼠标进入登陆框时:聚光灯效果(Spotlight)

 

2、点击登录按钮:

  1. import java.awt.AWTEvent;  
  2. import java.awt.AlphaComposite;  
  3. import java.awt.BasicStroke;  
  4. import java.awt.Color;  
  5. import java.awt.Composite;  
  6. import java.awt.Font;  
  7. import java.awt.Graphics;  
  8. import java.awt.Graphics2D;  
  9. import java.awt.Image;  
  10. import java.awt.Point;  
  11. import java.awt.RadialGradientPaint;  
  12. import java.awt.RenderingHints;  
  13. import java.awt.event.ActionEvent;  
  14. import java.awt.event.ActionListener;  
  15. import java.awt.event.FocusAdapter;  
  16. import java.awt.event.FocusEvent;  
  17. import java.awt.event.ItemEvent;  
  18. import java.awt.event.ItemListener;  
  19. import java.awt.event.MouseEvent;  
  20. import java.beans.PropertyChangeEvent;  
  21. import javax.swing.ImageIcon;  
  22. import javax.swing.JButton;  
  23. import javax.swing.JCheckBox;  
  24. import javax.swing.JComponent;  
  25. import javax.swing.JFrame;  
  26. import javax.swing.JLabel;  
  27. import javax.swing.JLayer;  
  28. import javax.swing.JPanel;  
  29. import javax.swing.JPasswordField;  
  30. import javax.swing.JTextField;  
  31. import javax.swing.SwingUtilities;  
  32. import javax.swing.Timer;  
  33. import javax.swing.UIManager;  
  34. import javax.swing.plaf.LayerUI;  
  35. /**  
  36.  * @author http://blog.csdn.net/Cannel_2020  
  37.  *  
  38.  */ 
  39. public class TestJLayer {  
  40.     private static JFrame loginFrame;  
  41.     private LoginLayerUI layerUI;//LayerUI的一个子类  
  42.     public static void main(String[] args) {  
  43.         try {  
  44.             UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");     
  45.         } catch (Exception e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.           
  49.         javax.swing.SwingUtilities.invokeLater(new Runnable() {  
  50.             public void run() {  
  51.                 new TestJLayer().createUI();  
  52.             }  
  53.         });  
  54.     }  
  55.     public void createUI() {  
  56.           
  57.         loginFrame = new JFrame("From Cannel_2020's blog(CSDN)");  
  58.         loginFrame.setSize(340260);  
  59.         loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  60.         loginFrame.setLocationRelativeTo(null);  
  61.           
  62.         JPanel panel = createPanel();  
  63.         layerUI = new LoginLayerUI();  
  64.         /*  
  65.          * JLayer的构造函数:JLayer(V view, LayerUI<V> ui),  
  66.          * 第一个参数view为Component的一个子类,就是要要装饰的Swing组件  
  67.          * 第二个参数为LayerUI<V>的一个实例,指定  
  68.          */ 
  69.         JLayer<JPanel> jlayer = new JLayer<JPanel>(panel, layerUI);  
  70.         //注意这个add的是JLayer<JPanel>的一个实例  
  71.         loginFrame.add(jlayer);  
  72.         loginFrame.setVisible(true);  
  73.     }  
  74.  
  75.     private JPanel createPanel() {  
  76.         final Image background = new ImageIcon("image/background.jpg").getImage();//背景图片  
  77.         JPanel panel = new JPanel() {  
  78.             private static final long serialVersionUID = 6246862165441423926L;  
  79.             public void paintComponent(Graphics g) {  
  80.                 super.paintComponent(g);  
  81.                 Graphics2D g2d = (Graphics2D) g;  
  82.                 g2d.drawImage(background, 00, loginFrame.getWidth(),  
  83.                         loginFrame.getHeight(), this);  
  84.             }  
  85.         };  
  86.         panel.setLayout(null);  
  87.           
  88.           
  89.         Font font = new Font("微软雅黑",Font.PLAIN,14);  
  90.         JLabel accountLabel = new JLabel("账号:");  
  91.         accountLabel.setFont(font);  
  92.         accountLabel.setBounds(40604015);  
  93.         JLabel pswLabel = new JLabel("密码:");  
  94.         pswLabel.setFont(font);  
  95.         pswLabel.setBounds(40984015);  
  96.           
  97.         final JTextField userName = new JTextField();  
  98.         userName.setFont(font);  
  99.         userName.setBounds(885315533);  
  100.         userName.addFocusListener(new FocusAdapter(){  
  101.             public void focusGained(FocusEvent e) {  
  102.                 userName.selectAll();  
  103.             }  
  104.         });  
  105.         JPasswordField password = new JPasswordField();  
  106.         password.setBounds(889015533);  
  107.         JLabel registerLabel = new JLabel("注册");  
  108.         registerLabel.setFont(font);  
  109.         registerLabel.setBounds(260602819);  
  110.         JLabel findBackLabel = new JLabel("找回");  
  111.         findBackLabel.setFont(font);  
  112.         findBackLabel.setBounds(260982819);  
  113.           
  114.         JCheckBox rmbCBox = new JCheckBox("记住密码");  
  115.         rmbCBox.setSelected(true);  
  116.         rmbCBox.setBounds(901407714);  
  117.         rmbCBox.addItemListener(new ItemListener(){  
  118.             public void itemStateChanged(ItemEvent e) {  
  119.                 if(e.getStateChange() == ItemEvent.DESELECTED){  
  120.                     System.out.println("rmbCBox(JCheckBox)被选中!");  
  121.                 }  
  122.             }  
  123.         });  
  124.         JCheckBox autoCBox = new JCheckBox("自动登录");  
  125.         autoCBox.setBounds(1751407714);  
  126.           
  127.         JButton setButton = new JButton("设置");  
  128.         setButton.setBounds(501707527);  
  129.           
  130.         JButton loginButton = new JButton("登录");  
  131.         loginButton.setFont(font);  
  132.         loginButton.setBounds(901707527);  
  133.         //5秒钟后停止  
  134.         final Timer stopper = new Timer(5000new ActionListener() {  
  135.             public void actionPerformed(ActionEvent ae) {  
  136.                 layerUI.stop();  
  137.             }  
  138.         });  
  139.         stopper.setRepeats(false);//设置计时器只在第一次时触发然后停止  
  140.  
  141.         loginButton.addActionListener(new ActionListener() {  
  142.             public void actionPerformed(ActionEvent ae) {  
  143.                 layerUI.start();  
  144.                 //若stopper不是在运行,则启动stopper。  
  145.                 if (!stopper.isRunning()) {  
  146.                     stopper.start();  
  147.                 }  
  148.             }  
  149.         });  
  150.           
  151.         JButton exitButton = new JButton("退出");  
  152.         exitButton.setFont(font);  
  153.         exitButton.setBounds(1701707527);  
  154.         exitButton.addActionListener(new ActionListener()  
  155.         {  
  156.             public void actionPerformed(ActionEvent e) {  
  157.                 System.exit(0);  
  158.             }  
  159.               
  160.         });  
  161.           
  162.         panel.add(userName);  
  163.         panel.add(password);  
  164.         panel.add(accountLabel);  
  165.         panel.add(pswLabel);  
  166.         panel.add(registerLabel);  
  167.         panel.add(findBackLabel);  
  168.         panel.add(rmbCBox);  
  169.         panel.add(autoCBox);  
  170.         panel.add(loginButton);  
  171.         panel.add(exitButton);  
  172.           
  173.         return panel;  
  174.  
  175.  
  176.     }  
  177. }  
  178. class LoginLayerUI extends LayerUI<JPanel> implements ActionListener {  
  179.  
  180.     private static final long serialVersionUID = 1L;  
  181.     private boolean mIsRunning = false;// 点击按钮之后所触发的线程是否在运行  
  182.     private boolean mIsFadingOut = false;//控制线程的停止,和处理  
  183.     private Timer mTimer;// 在指定时间间隔触发一个或多个 ActionEvent。  
  184.  
  185.     private int mAngle = 0;//用于旋转时计算角度  
  186.     private int mFadeCount = 0;//结合mFadeLimit用于设置针形旋转图案整体的渐变的效果  
  187.     private int mFadeLimit = 30;  
  188.  
  189.     private boolean mActive;// 是否进入窗口内  
  190.     private int mX, mY;// 记录鼠标的坐标  
  191.     /*  
  192.      * 渲染效果的过程中会不断调用paint  
  193.      */ 
  194.     public void paint(Graphics g, JComponent c) {  
  195.         int w = c.getWidth();//获取组件c的宽度  
  196.         int h = c.getHeight();  
  197.         super.paint(g, c);//调用父类的paint方法,绘画组件c  
  198.  
  199.         Graphics2D g2 = (Graphics2D) g.create();  
  200.         // 设置聚光灯(Spotlight)效果  
  201.         if (mActive) {  
  202.             // 创建径向渐变,中间透明。  
  203.             java.awt.geom.Point2D center = new java.awt.geom.Point2D.Float(mX,  
  204.                     mY);  
  205.             float radius = 72;  
  206.             float[] dist = { 0.0f, 1.0f };  
  207.             Color[] colors = { new Color(0.0f, 0.0f, 0.0f, 0.0f), Color.black };  
  208.             //RadialGradientPaint 类提供使用圆形辐射颜色渐变模式填充某一形状的方式  
  209.             RadialGradientPaint p = new RadialGradientPaint(center, radius,  
  210.                     dist, colors);  
  211.             //setPaint:为 Graphics2D 上下文设置 Paint 属性  
  212.             g2.setPaint(p);  
  213.             /*为 Graphics2D 上下文设置 Composite。   
  214.              *Composite 用于所有绘制方法中,如 drawImage、drawString、draw 和 fill  
  215.              *这里使用AlphaComposite 类实现一些基本的 alpha 合成规则  
  216.              *将源色与目标色组合,在图形和图像中实现混合和透明效果  
  217.              */ 
  218.             g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,  
  219.                     .6f));  
  220.             //填充是绘画  
  221.             g2.fillRect(00, c.getWidth(), c.getHeight());  
  222.         }  
  223.           
  224.           
  225.         if (!mIsRunning) {  
  226.             return;  
  227.         }  
  228.         float fade = (float) mFadeCount / (float) mFadeLimit;  
  229.         //fade的不同形成:12根针整体刚才出现的渐变效果,和登录成功后的针消失过程的渐变效果  
  230.         g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,  
  231.                 .5f * fade));  
  232.         g2.fillRect(00, w, h);  
  233.  
  234.         int s = Math.min(w, h) / 5;  
  235.         int cx = w / 2;  
  236.         int cy = h / 2;  
  237.         /* 为呈现算法设置单个首选项的值。  
  238.          * RenderingHints.KEY_ANTIALIASING:抗锯齿提示键。  
  239.          * RenderingHints.VALUE_ANTIALIAS_ON:抗锯齿提示值——使用抗锯齿模式完成呈现  
  240.          */ 
  241.         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
  242.                 RenderingHints.VALUE_ANTIALIAS_ON);  
  243.  
  244.         /*  
  245.          *  setStroke:设置呈现过程中要画的图形  
  246.          * BasicStroke 类定义针对图形图元轮廓呈现属性的一个基本集合  
  247.          */ 
  248.         g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND,  
  249.                 BasicStroke.JOIN_ROUND));  
  250.         //设置绘画颜色  
  251.         g2.setPaint(Color.white);  
  252.         /* rotate:旋转转换连接  
  253.          * 第一个参数 Math.PI * mAngle / 180:旋转的角度,以弧度为单位  
  254.          * 第二个参数 cx:x - 旋转原点的 x 坐标  
  255.          * 第二个参数 cy:y - 旋转原点的 y 坐标  
  256.          */ 
  257.         g2.rotate(Math.PI * mAngle / 180, cx, cy);  
  258.           
  259.         //12跟针,各个针的颜色是不同的,针与针之间形成渐变的效果  
  260.         for (int i = 0; i < 12; i++) {  
  261.             float scale = (11.0f - (float) i) / 11.0f;  
  262.             g2.drawLine(cx + s, cy, cx + s * 2, cy);  
  263.             g2.rotate(-Math.PI / 6, cx, cy);  
  264.             //通过设置AlphaComposite.getInstance()第二个参数的不同来实现12“针”颜色的不同  
  265.             g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,  
  266.                     scale * fade));  
  267.         }  
  268.         //释放此图形的上下文以及它使用的所有系统资源。   
  269.         g2.dispose();  
  270.     }  
  271.  
  272.     public void installUI(JComponent c) {  
  273.         super.installUI(c);  
  274.         JLayer jlayer = (JLayer) c;  
  275.         // 启动鼠标事件和鼠标移动事件  
  276.         jlayer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK  
  277.                 | AWTEvent.MOUSE_MOTION_EVENT_MASK);  
  278.     }  
  279.  
  280.     public void uninstallUI(JComponent c) {  
  281.         JLayer jlayer = (JLayer) c;  
  282.         jlayer.setLayerEventMask(0);  
  283.         super.uninstallUI(c);  
  284.     }  
  285.  
  286.     // JLayer对象专用的鼠标事件,在installUI中启动事件,在uninstallUI中禁用事件  
  287.     protected void processMouseEvent(MouseEvent e, JLayer l) {  
  288.         if (e.getID() == MouseEvent.MOUSE_ENTERED)  
  289.             mActive = true;  
  290.         if (e.getID() == MouseEvent.MOUSE_EXITED)  
  291.             mActive = false;  
  292.         l.repaint();  
  293.     }  
  294.  
  295.     // JLayer对象专用的鼠标移动事件,在installUI中启动事件,在uninstallUI中禁用事件  
  296.     // 这里把鼠标坐标记录在mX和mY中  
  297.     protected void processMouseMotionEvent(MouseEvent e, JLayer l) {  
  298.         // 确定鼠标移动事件相对于层的坐标位置。  
  299.         Point p = SwingUtilities  
  300.                 .convertPoint(e.getComponent(), e.getPoint(), l);  
  301.         mX = p.x;  
  302.         mY = p.y;  
  303.         l.repaint();  
  304.     }  
  305.  
  306.     public void actionPerformed(ActionEvent e) {  
  307.         if (mIsRunning) {  
  308.             //firePropertyChange():通知的内部状态的更新  
  309.             firePropertyChange("tick"01);  
  310.             mAngle += 3;  
  311.             if (mAngle >= 360) {  
  312.                 mAngle = 0;  
  313.             }  
  314.             if (mIsFadingOut) {  
  315.                 if (--mFadeCount == 0) {  
  316.                     mIsRunning = false;  
  317.                     mTimer.stop();  
  318.                 }  
  319.             //防止AlphaComposite.getInstance()的第二个参数的值超出范围  
  320.             } else if (mFadeCount < mFadeLimit) {  
  321.                 mFadeCount++;  
  322.             }  
  323.         }  
  324.     }  
  325.  
  326.     public void start() {  
  327.         if (mIsRunning) {  
  328.             return;  
  329.         }  
  330.         mIsRunning = true;  
  331.         mIsFadingOut = false;  
  332.         mFadeCount = 0;  
  333.         int fps = 24;  
  334.         int tick = 1000 / fps;  
  335.         //每tick毫秒调用一次本类中的actionPerformed方法  
  336.         mTimer = new Timer(tick, this);  
  337.         mTimer.start();  
  338.     }  
  339.  
  340.     public void stop() {  
  341.         mIsFadingOut = true;  
  342.     }  
  343.     //不断repaint()窗口  
  344.     public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {  
  345.         if ("tick".equals(pce.getPropertyName())) {  
  346.             l.repaint();  
  347.         }  
  348.     }  

原文链接:http://blog.csdn.net/cannel_2020/article/details/7350516

【编辑推荐】

  1. 关于Java中内存溢出的解决办法
  2. Java中的面向对象特性
  3. 探究Java初始化的过程
  4. Java集合框架的知识总结
  5. Java与F#的并行程序处理对比
责任编辑:林师授 来源: Cannel_2020的博客
相关推荐

2010-06-28 09:26:15

JDK 7Swing组件Java

2022-09-07 10:20:05

Python装饰类

2018-08-20 16:25:48

编程语言Java异常处理

2009-04-09 08:59:33

Windows 7微软操作系统

2020-04-13 16:05:25

JS装饰器前端

2011-07-29 09:43:52

Java SE 7

2011-12-07 10:46:25

Java

2009-07-15 11:02:32

Swing组件

2009-07-14 17:21:42

Swing组件

2009-07-10 16:29:32

Swing组件

2009-07-10 09:38:06

Java swing组

2011-12-14 15:53:51

云计算

2011-03-24 09:34:41

SPRING

2009-07-10 10:19:57

JFormattedTSwing

2011-04-01 09:49:54

Python

2015-03-10 11:21:44

JavaScript组JavaScript

2009-06-09 16:14:47

Java swing组件串行化

2009-07-10 13:20:37

Swing容器组件

2010-06-10 09:26:22

Java 7

2009-10-20 14:10:00

CCIE经验
点赞
收藏

51CTO技术栈公众号