Java7的一個新類——JLayer:裝飾的Swing組件

來源:互聯網
上載者:User

Java7中的一個新的類,JLayer,也已被添加到提高的Java Swing的能力。 JLayer主要用於裝飾的Swing組件。你可以用它改變如何繪製組件,以及它們如何響應事件。下面是這個類的一個簡單的例子:

先看運行結果:

1、滑鼠進入登陸框時:聚光燈效果(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的建構函式:JLayer(V view, LayerUI<V> ui), * 第一個參數view為Component的一個子類,就是要要裝飾的Swing組件 * 第二個參數為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("設定");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);//設定計時器只在第一次時觸發然後停止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;// 點擊按鈕之後所觸發的線程是否在運行private boolean mIsFadingOut = false;//控制線程的停止,和處理private Timer mTimer;// 在指定時間間隔觸發一個或多個 ActionEvent。private int mAngle = 0;//用於旋轉時計算角度private int mFadeCount = 0;//結合mFadeLimit用於設定針形旋轉圖案整體的漸層的效果private int mFadeLimit = 30;private boolean mActive;// 是否進入視窗內private int mX, mY;// 記錄滑鼠的座標/* * 渲染效果的過程中會不斷調用paint */public void paint(Graphics g, JComponent c) {int w = c.getWidth();//擷取組件c的寬度int h = c.getHeight();super.paint(g, c);//調用父類的paint方法,繪畫組件cGraphics2D g2 = (Graphics2D) g.create();// 設定聚光燈(Spotlight)效果if (mActive) {// 建立放射狀漸層,中間透明。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 上下文設定 Paint 屬性g2.setPaint(p);/*為 Graphics2D 上下文設定 Composite。  *Composite 用於所有繪製方法中,如 drawImage、drawString、draw 和 fill *這裡使用AlphaComposite 類實現一些基本的 alpha 合成規則 *將源色與目標色組合,在圖形和映像中實現混合和透明效果 */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根針整體剛才出現的漸層效果,和登入成功後的針消失過程的漸層效果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;/* 為呈現演算法設定單個喜好設定的值。 * RenderingHints.KEY_ANTIALIASING:消除鋸齒提示鍵。 * RenderingHints.VALUE_ANTIALIAS_ON:消除鋸齒提示值——使用消除鋸齒模式完成呈現 */g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);/* *  setStroke:設定呈現過程中要畫的圖形 * BasicStroke 類定義針對圖形圖元輪廓呈現屬性的一個基本集合 */g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));//設定繪畫顏色g2.setPaint(Color.white);/* rotate:旋轉轉換串連 * 第一個參數 Math.PI * mAngle / 180:旋轉的角度,以弧度為單位 * 第二個參數 cx:x - 旋轉原點的 x 座標 * 第二個參數 cy:y - 旋轉原點的 y 座標 */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);//通過設定AlphaComposite.getInstance()第二個參數的不同來實現12“針”顏色的不同g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,scale * fade));}//釋放此圖形的上下文以及它使用的所有系統資源。 g2.dispose();}public void installUI(JComponent c) {super.installUI(c);JLayer jlayer = (JLayer) c;// 啟動滑鼠事件和滑鼠移動事件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對象專用的滑鼠事件,在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對象專用的滑鼠移動事件,在installUI中啟動事件,在uninstallUI中禁用事件// 這裡把滑鼠座標記錄在mX和mY中protected void processMouseMotionEvent(MouseEvent e, JLayer l) {// 確定滑鼠移動事件相對於層的座標位置。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():通知的內部狀態的更新firePropertyChange("tick", 0, 1);mAngle += 3;if (mAngle >= 360) {mAngle = 0;}if (mIsFadingOut) {if (--mFadeCount == 0) {mIsRunning = false;mTimer.stop();}//防止AlphaComposite.getInstance()的第二個參數的值超出範圍} 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毫秒調用一次本類中的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();}}}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.