Java7的一個新類JLayer:裝飾的Swing組件
作者:Cannel_2020
Java7中的一個新的類,JLayer,也已被添加到提高的Java Swing的能力。 JLayer主要用于裝飾的Swing組件。你可以用它改變?nèi)绾卫L制組件,以及它們?nèi)绾雾憫?yīng)事件。
Java7中的一個新的類,JLayer,也已被添加到提高的Java Swing的能力。 JLayer主要用于裝飾的Swing組件。你可以用它改變?nèi)绾卫L制組件,以及它們?nèi)绾雾憫?yīng)事件。
下面是這個類的一個簡單的例子:
先看運行結(jié)果:
1、鼠標(biāo)進入登陸框時:聚光燈效果(Spotlight)
2、點擊登錄按鈕:
- import java.awt.AWTEvent;
- import java.awt.AlphaComposite;
- import java.awt.BasicStroke;
- import java.awt.Color;
- import java.awt.Composite;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Image;
- import java.awt.Point;
- import java.awt.RadialGradientPaint;
- import java.awt.RenderingHints;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.FocusAdapter;
- import java.awt.event.FocusEvent;
- import java.awt.event.ItemEvent;
- import java.awt.event.ItemListener;
- import java.awt.event.MouseEvent;
- import java.beans.PropertyChangeEvent;
- import javax.swing.ImageIcon;
- import javax.swing.JButton;
- import javax.swing.JCheckBox;
- import javax.swing.JComponent;
- import javax.swing.JFrame;
- import javax.swing.JLabel;
- import javax.swing.JLayer;
- import javax.swing.JPanel;
- import javax.swing.JPasswordField;
- import javax.swing.JTextField;
- import javax.swing.SwingUtilities;
- import javax.swing.Timer;
- import javax.swing.UIManager;
- import javax.swing.plaf.LayerUI;
- /**
- * @author http://blog.csdn.net/Cannel_2020
- *
- */
- public class TestJLayer {
- private static JFrame loginFrame;
- private LoginLayerUI layerUI;//LayerUI的一個子類
- public static void main(String[] args) {
- try {
- UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
- } catch (Exception e) {
- e.printStackTrace();
- }
- javax.swing.SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- new TestJLayer().createUI();
- }
- });
- }
- public void createUI() {
- loginFrame = new JFrame("From Cannel_2020's blog(CSDN)");
- loginFrame.setSize(340, 260);
- loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- loginFrame.setLocationRelativeTo(null);
- JPanel panel = createPanel();
- layerUI = new LoginLayerUI();
- /*
- * JLayer的構(gòu)造函數(shù):JLayer(V view, LayerUI<V> ui),
- * 第一個參數(shù)view為Component的一個子類,就是要要裝飾的Swing組件
- * 第二個參數(shù)為LayerUI<V>的一個實例,指定
- */
- JLayer<JPanel> jlayer = new JLayer<JPanel>(panel, layerUI);
- //注意這個add的是JLayer<JPanel>的一個實例
- loginFrame.add(jlayer);
- loginFrame.setVisible(true);
- }
- private JPanel createPanel() {
- final Image background = new ImageIcon("image/background.jpg").getImage();//背景圖片
- JPanel panel = new JPanel() {
- private static final long serialVersionUID = 6246862165441423926L;
- public void paintComponent(Graphics g) {
- super.paintComponent(g);
- Graphics2D g2d = (Graphics2D) g;
- g2d.drawImage(background, 0, 0, loginFrame.getWidth(),
- loginFrame.getHeight(), this);
- }
- };
- panel.setLayout(null);
- Font font = new Font("微軟雅黑",Font.PLAIN,14);
- JLabel accountLabel = new JLabel("賬號:");
- accountLabel.setFont(font);
- accountLabel.setBounds(40, 60, 40, 15);
- JLabel pswLabel = new JLabel("密碼:");
- pswLabel.setFont(font);
- pswLabel.setBounds(40, 98, 40, 15);
- final JTextField userName = new JTextField();
- userName.setFont(font);
- userName.setBounds(88, 53, 155, 33);
- userName.addFocusListener(new FocusAdapter(){
- public void focusGained(FocusEvent e) {
- userName.selectAll();
- }
- });
- JPasswordField password = new JPasswordField();
- password.setBounds(88, 90, 155, 33);
- JLabel registerLabel = new JLabel("注冊");
- registerLabel.setFont(font);
- registerLabel.setBounds(260, 60, 28, 19);
- JLabel findBackLabel = new JLabel("找回");
- findBackLabel.setFont(font);
- findBackLabel.setBounds(260, 98, 28, 19);
- JCheckBox rmbCBox = new JCheckBox("記住密碼");
- rmbCBox.setSelected(true);
- rmbCBox.setBounds(90, 140, 77, 14);
- rmbCBox.addItemListener(new ItemListener(){
- public void itemStateChanged(ItemEvent e) {
- if(e.getStateChange() == ItemEvent.DESELECTED){
- System.out.println("rmbCBox(JCheckBox)被選中!");
- }
- }
- });
- JCheckBox autoCBox = new JCheckBox("自動登錄");
- autoCBox.setBounds(175, 140, 77, 14);
- JButton setButton = new JButton("設(shè)置");
- setButton.setBounds(50, 170, 75, 27);
- JButton loginButton = new JButton("登錄");
- loginButton.setFont(font);
- loginButton.setBounds(90, 170, 75, 27);
- //5秒鐘后停止
- final Timer stopper = new Timer(5000, new ActionListener() {
- public void actionPerformed(ActionEvent ae) {
- layerUI.stop();
- }
- });
- stopper.setRepeats(false);//設(shè)置計時器只在第一次時觸發(fā)然后停止
- loginButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent ae) {
- layerUI.start();
- //若stopper不是在運行,則啟動stopper。
- if (!stopper.isRunning()) {
- stopper.start();
- }
- }
- });
- JButton exitButton = new JButton("退出");
- exitButton.setFont(font);
- exitButton.setBounds(170, 170, 75, 27);
- exitButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e) {
- System.exit(0);
- }
- });
- panel.add(userName);
- panel.add(password);
- panel.add(accountLabel);
- panel.add(pswLabel);
- panel.add(registerLabel);
- panel.add(findBackLabel);
- panel.add(rmbCBox);
- panel.add(autoCBox);
- panel.add(loginButton);
- panel.add(exitButton);
- return panel;
- }
- }
- class LoginLayerUI extends LayerUI<JPanel> implements ActionListener {
- private static final long serialVersionUID = 1L;
- private boolean mIsRunning = false;// 點擊按鈕之后所觸發(fā)的線程是否在運行
- private boolean mIsFadingOut = false;//控制線程的停止,和處理
- private Timer mTimer;// 在指定時間間隔觸發(fā)一個或多個 ActionEvent。
- private int mAngle = 0;//用于旋轉(zhuǎn)時計算角度
- private int mFadeCount = 0;//結(jié)合mFadeLimit用于設(shè)置針形旋轉(zhuǎn)圖案整體的漸變的效果
- private int mFadeLimit = 30;
- private boolean mActive;// 是否進入窗口內(nèi)
- private int mX, mY;// 記錄鼠標(biāo)的坐標(biāo)
- /*
- * 渲染效果的過程中會不斷調(diào)用paint
- */
- public void paint(Graphics g, JComponent c) {
- int w = c.getWidth();//獲取組件c的寬度
- int h = c.getHeight();
- super.paint(g, c);//調(diào)用父類的paint方法,繪畫組件c
- Graphics2D g2 = (Graphics2D) g.create();
- // 設(shè)置聚光燈(Spotlight)效果
- if (mActive) {
- // 創(chuàng)建徑向漸變,中間透明。
- java.awt.geom.Point2D center = new java.awt.geom.Point2D.Float(mX,
- mY);
- float radius = 72;
- float[] dist = { 0.0f, 1.0f };
- Color[] colors = { new Color(0.0f, 0.0f, 0.0f, 0.0f), Color.black };
- //RadialGradientPaint 類提供使用圓形輻射顏色漸變模式填充某一形狀的方式
- RadialGradientPaint p = new RadialGradientPaint(center, radius,
- dist, colors);
- //setPaint:為 Graphics2D 上下文設(shè)置 Paint 屬性
- g2.setPaint(p);
- /*為 Graphics2D 上下文設(shè)置 Composite。
- *Composite 用于所有繪制方法中,如 drawImage、drawString、draw 和 fill
- *這里使用AlphaComposite 類實現(xiàn)一些基本的 alpha 合成規(guī)則
- *將源色與目標(biāo)色組合,在圖形和圖像中實現(xiàn)混合和透明效果
- */
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
- .6f));
- //填充是繪畫
- g2.fillRect(0, 0, c.getWidth(), c.getHeight());
- }
- if (!mIsRunning) {
- return;
- }
- float fade = (float) mFadeCount / (float) mFadeLimit;
- //fade的不同形成:12根針整體剛才出現(xiàn)的漸變效果,和登錄成功后的針消失過程的漸變效果
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
- .5f * fade));
- g2.fillRect(0, 0, w, h);
- int s = Math.min(w, h) / 5;
- int cx = w / 2;
- int cy = h / 2;
- /* 為呈現(xiàn)算法設(shè)置單個首選項的值。
- * RenderingHints.KEY_ANTIALIASING:抗鋸齒提示鍵。
- * RenderingHints.VALUE_ANTIALIAS_ON:抗鋸齒提示值——使用抗鋸齒模式完成呈現(xiàn)
- */
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- /*
- * setStroke:設(shè)置呈現(xiàn)過程中要畫的圖形
- * BasicStroke 類定義針對圖形圖元輪廓呈現(xiàn)屬性的一個基本集合
- */
- g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND,
- BasicStroke.JOIN_ROUND));
- //設(shè)置繪畫顏色
- g2.setPaint(Color.white);
- /* rotate:旋轉(zhuǎn)轉(zhuǎn)換連接
- * 第一個參數(shù) Math.PI * mAngle / 180:旋轉(zhuǎn)的角度,以弧度為單位
- * 第二個參數(shù) cx:x - 旋轉(zhuǎn)原點的 x 坐標(biāo)
- * 第二個參數(shù) cy:y - 旋轉(zhuǎn)原點的 y 坐標(biāo)
- */
- g2.rotate(Math.PI * mAngle / 180, cx, cy);
- //12跟針,各個針的顏色是不同的,針與針之間形成漸變的效果
- for (int i = 0; i < 12; i++) {
- float scale = (11.0f - (float) i) / 11.0f;
- g2.drawLine(cx + s, cy, cx + s * 2, cy);
- g2.rotate(-Math.PI / 6, cx, cy);
- //通過設(shè)置AlphaComposite.getInstance()第二個參數(shù)的不同來實現(xiàn)12“針”顏色的不同
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
- scale * fade));
- }
- //釋放此圖形的上下文以及它使用的所有系統(tǒng)資源。
- g2.dispose();
- }
- public void installUI(JComponent c) {
- super.installUI(c);
- JLayer jlayer = (JLayer) c;
- // 啟動鼠標(biāo)事件和鼠標(biāo)移動事件
- jlayer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK
- | AWTEvent.MOUSE_MOTION_EVENT_MASK);
- }
- public void uninstallUI(JComponent c) {
- JLayer jlayer = (JLayer) c;
- jlayer.setLayerEventMask(0);
- super.uninstallUI(c);
- }
- // JLayer對象專用的鼠標(biāo)事件,在installUI中啟動事件,在uninstallUI中禁用事件
- protected void processMouseEvent(MouseEvent e, JLayer l) {
- if (e.getID() == MouseEvent.MOUSE_ENTERED)
- mActive = true;
- if (e.getID() == MouseEvent.MOUSE_EXITED)
- mActive = false;
- l.repaint();
- }
- // JLayer對象專用的鼠標(biāo)移動事件,在installUI中啟動事件,在uninstallUI中禁用事件
- // 這里把鼠標(biāo)坐標(biāo)記錄在mX和mY中
- protected void processMouseMotionEvent(MouseEvent e, JLayer l) {
- // 確定鼠標(biāo)移動事件相對于層的坐標(biāo)位置。
- Point p = SwingUtilities
- .convertPoint(e.getComponent(), e.getPoint(), l);
- mX = p.x;
- mY = p.y;
- l.repaint();
- }
- public void actionPerformed(ActionEvent e) {
- if (mIsRunning) {
- //firePropertyChange():通知的內(nèi)部狀態(tài)的更新
- firePropertyChange("tick", 0, 1);
- mAngle += 3;
- if (mAngle >= 360) {
- mAngle = 0;
- }
- if (mIsFadingOut) {
- if (--mFadeCount == 0) {
- mIsRunning = false;
- mTimer.stop();
- }
- //防止AlphaComposite.getInstance()的第二個參數(shù)的值超出范圍
- } else if (mFadeCount < mFadeLimit) {
- mFadeCount++;
- }
- }
- }
- public void start() {
- if (mIsRunning) {
- return;
- }
- mIsRunning = true;
- mIsFadingOut = false;
- mFadeCount = 0;
- int fps = 24;
- int tick = 1000 / fps;
- //每tick毫秒調(diào)用一次本類中的actionPerformed方法
- mTimer = new Timer(tick, this);
- mTimer.start();
- }
- public void stop() {
- mIsFadingOut = true;
- }
- //不斷repaint()窗口
- public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {
- if ("tick".equals(pce.getPropertyName())) {
- l.repaint();
- }
- }
- }
原文鏈接:http://blog.csdn.net/cannel_2020/article/details/7350516
【編輯推薦】
責(zé)任編輯:林師授
來源:
Cannel_2020的博客