Swing换肤

fearlessMore 2013-12-30 09:30:39
加精
-->

源码:
package com.han.lnf;

import java.awt.AWTEvent;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.text.ParseException;

import javax.swing.ButtonGroup;
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.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import javax.swing.plaf.LayerUI;
import javax.swing.plaf.synth.SynthLookAndFeel;

/**
* Use a spotlight layer as a JLayer to render a JFrame.
* <p>
* The default opaque style specified in this L&F is false.
*
* @author Administrator
*/
public class JSpotlightLayer extends JPanel {
private static final long serialVersionUID = -3416068588759196883L;
private static JButton orderButton;

public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}

private static void createAndShowGUI() {
initLookAndFeel();// specify the L&F
LayerUI<JPanel> layerUI = new SpotlightLayerUI();
JPanel contentPane = new JSpotlightLayer();
JLayer<JPanel> jlayer = new JLayer<>(contentPane, layerUI);
final JFrame f = new JFrame("SpotlightLayerUI");
f.add(jlayer);
f.getRootPane().setDefaultButton(orderButton);
f.setSize(270, 185);
f.setResizable(false);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setVisible(true);
}

private static void initLookAndFeel() {
SynthLookAndFeel lookAndFeel = new SynthLookAndFeel();
try {
lookAndFeel.load(JSpotlightLayer.class
.getResourceAsStream("lnfimpl/synth.xml"),
JSpotlightLayer.class);
} catch (ParseException e) {
System.err.println("There is an error in parsing xml of Synth");
System.err.println("Using the default look and feel");
e.printStackTrace();
}
try {
UIManager.setLookAndFeel(lookAndFeel);
} catch (UnsupportedLookAndFeelException e) {
System.err.println("Synth is not a supported look and feel");
System.err.println("Using the default look and feel");
e.printStackTrace();
}
}

private static class SpotlightLayerUI extends LayerUI<JPanel> {
private static final long serialVersionUID = -2815331572730280489L;
private boolean mActive;
private int mX, mY;

@Override
public void installUI(JComponent c) {
super.installUI(c);
@SuppressWarnings("unchecked")
JLayer<JPanel> jlayer = (JLayer<JPanel>) c;
jlayer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK);
}

@Override
public void uninstallUI(JComponent c) {
super.uninstallUI(c);
@SuppressWarnings("unchecked")
JLayer<JPanel> jlayer = (JLayer<JPanel>) c;
jlayer.setLayerEventMask(0);
}

@Override
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
Graphics2D g2 = (Graphics2D) g.create();
if (mActive) {
/* Create a radial gradient, transparent in the middle */
Point2D center = new 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 p = new RadialGradientPaint(center, radius,
dist, colors);
g2.setPaint(p);
g2.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, .6f));
g2.fillRect(0, 0, c.getWidth(), c.getHeight());
}
g2.dispose();
}

@Override
protected void processMouseEvent(MouseEvent e,
JLayer<? extends JPanel> l) {
if (e.getID() == MouseEvent.MOUSE_ENTERED) {
mActive = true;
} else if (e.getID() == MouseEvent.MOUSE_EXITED) {
mActive = false;
}
l.repaint();
}

@Override
protected void processMouseMotionEvent(MouseEvent e,
JLayer<? extends JPanel> l) {
Point p = SwingUtilities.convertPoint(e.getComponent(),
e.getPoint(), l);
mX = p.x;
mY = p.y;
l.repaint();
}
}

JSpotlightLayer() {
ButtonGroup entreeGroup = new ButtonGroup();
JRadioButton radioButton = new JRadioButton("Beef", true);
JRadioButton radioButton2 = new JRadioButton("Chicken");
JRadioButton radioButton3 = new JRadioButton("Vegetable");
entreeGroup.add(radioButton);
entreeGroup.add(radioButton2);
entreeGroup.add(radioButton3);
JCheckBox jCheckBox = new JCheckBox("Ketchup");
JCheckBox jCheckBox2 = new JCheckBox("Mustard");
JCheckBox jCheckBox3 = new JCheckBox("Pickles");
JLabel label = new JLabel("Special requests:");
JTextField tf = new JTextField(15);
orderButton = new JButton("Place Order");
orderButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("default button clicked");
System.exit(0);// normal termination of JVM
}
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("cancel button clicked");
System.exit(0);// normal termination of JVM
}
});
add(radioButton);
add(radioButton2);
add(radioButton3);
add(jCheckBox);
add(jCheckBox2);
add(jCheckBox3);
add(label);
add(tf);
add(orderButton);
add(cancelButton);
}
}
...全文
4763 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
XHRGL 2014-05-18
  • 打赏
  • 举报
回复
太漂亮了,怎样做到的,给个学习方向吧
qcymkxyc 2014-01-21
  • 打赏
  • 举报
回复
1046838702 2014-01-15
  • 打赏
  • 举报
回复
学习了
fearlessMore 2014-01-10
  • 打赏
  • 举报
回复
引用 37 楼 jeckykang 的回复:
[quote=引用 18 楼 Gaowen_HAN 的回复:] 利用 Synth 可以创建出完全专业的外观,Java 1.4 中发布的 GTK+ 和 Windows XP 外观就完全是用 Synth 创建的。(那时它不是一个已公布的 API。) 由于我上面的例子实践中用了20张png图片,加载速度以及内存占用比Metal的L&F可能差一点,不过如果是复杂界面或者创建数量多的Components时,Synth和Metal还是差不多的。比如,我这个例子中(XP + JDK7u45 + Eclipse Kepler)如果注销掉
initLookAndFeel();// specify the L&F
这行代码,得到的Metal经典外观时占用的内存为25Kb,如果不注销,使用的定制的外观时内存为29Kb,这些内存和启动速度我觉得都比JavaFX应用要好。 如果使用100 个组件的界面来测试:
为啥Synth是最慢的?Ocean那个没听说过。[/quote]Ocean就是Metal的一个Theme
曾见孤鸿影 2014-01-10
  • 打赏
  • 举报
回复
为何这么掉!
异常异长 2014-01-10
  • 打赏
  • 举报
回复
感谢分享 确实不错
长乐子 2014-01-10
  • 打赏
  • 举报
回复
引用 18 楼 Gaowen_HAN 的回复:
利用 Synth 可以创建出完全专业的外观,Java 1.4 中发布的 GTK+ 和 Windows XP 外观就完全是用 Synth 创建的。(那时它不是一个已公布的 API。) 由于我上面的例子实践中用了20张png图片,加载速度以及内存占用比Metal的L&F可能差一点,不过如果是复杂界面或者创建数量多的Components时,Synth和Metal还是差不多的。比如,我这个例子中(XP + JDK7u45 + Eclipse Kepler)如果注销掉
initLookAndFeel();// specify the L&F
这行代码,得到的Metal经典外观时占用的内存为25Kb,如果不注销,使用的定制的外观时内存为29Kb,这些内存和启动速度我觉得都比JavaFX应用要好。 如果使用100 个组件的界面来测试:
为啥Synth是最慢的?Ocean那个没听说过。
fearlessMore 2014-01-08
  • 打赏
  • 举报
回复
遇到一个问题: 当使用自定义感官时,比如我上面的L&F或者使用jgoodies的UIManager.setLookAndFeel(new com.jgoodies.looks.windows.WindowsLookAndFeel()); 则如果定义文本框等,像JTextField,JTextPane时,在用智能拼音输入时,输入窗口会出现方框形式的乱码。取消这种观感的设置既可解决问题(比如注销掉initLookAndFeel();// specify the L&F)。原因是这种观感不支持中文。怎么让自定义的感官支持呢?
fearlessMore 2014-01-08
  • 打赏
  • 举报
回复
引用 35 楼 Gaowen_HAN 的回复:
遇到一个问题: 当使用自定义感官时,比如我上面的L&F或者使用jgoodies的UIManager.setLookAndFeel(new com.jgoodies.looks.windows.WindowsLookAndFeel()); 则如果定义文本框等,像JTextField,JTextPane时,在用智能拼音输入时,输入窗口会出现方框形式的乱码。取消这种观感的设置既可解决问题(比如注销掉initLookAndFeel();// specify the L&F)。原因是这种观感不支持中文。怎么让自定义的感官支持呢?
解决了,是因为字体的原因,Arial不支持中文的显示。改为雅黑就行了,可以使用Component的getFont()以及Font的canDisplay(int codePoint)或者canDisplayUpTo(String)来判断是否支持特定的字符显示。
F_Cindy 2014-01-07
  • 打赏
  • 举报
回复
fearlessMore 2014-01-05
  • 打赏
  • 举报
回复
引用 29 楼 Gaowen_HAN 的回复:
引用 28 楼 ruishenh 的回复:
只是一个小例子,为了说明问题而已。具体的美化因人而异,以及代码的拓展读者可以自己玩玩~
又玩了下,加了个animation动画效果(按下default button -- order button 或 按下enter键启动动画): 更新后的源代码:
package com.han.lnf;

import java.awt.AWTEvent;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.MouseEvent;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
import java.text.ParseException;

import javax.swing.ButtonGroup;
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.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import javax.swing.plaf.LayerUI;
import javax.swing.plaf.synth.SynthLookAndFeel;

/**
 * Use a custom L&F to render JFrame.
 * 
 * @author Administrator
 */
public class TestCase extends JPanel {
	private static final long serialVersionUID = -3416068588759196883L;
	private static JLayer<JPanel> jLayer;
	private static LayerUI<JPanel> spotlightLayerUI;
	private static WaitLayerUI waitLayerUI;
	private static Timer stopper;
	private static JButton orderButton;

	public static void main(String[] args) {
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				createAndShowGUI();
			}
		});
	}

	private static void createAndShowGUI() {
		initLookAndFeel();// specify the L&F
		spotlightLayerUI = new SpotlightLayerUI();
		waitLayerUI = new WaitLayerUI();
		stopper = new Timer(4000, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				waitLayerUI.stop();
				jLayer.setUI(spotlightLayerUI);
			}
		});
		stopper.setRepeats(false);
		JPanel contentPane = new TestCase();
		jLayer = new JLayer<>(contentPane, spotlightLayerUI);
		final JFrame f = new JFrame("Custom L&F");
		f.add(jLayer);
		f.getRootPane().setDefaultButton(orderButton);
		f.setSize(270, 185);
		f.setResizable(false);
		f.setLocationRelativeTo(null);
		f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		f.setVisible(true);
	}

	private static void initLookAndFeel() {
		SynthLookAndFeel lookAndFeel = new SynthLookAndFeel();
		try {
			lookAndFeel.load(
					TestCase.class.getResourceAsStream("lnfimpl/synth.xml"),
					TestCase.class);
		} catch (ParseException e) {
			System.err.println("There is an error in parsing xml of Synth");
			e.printStackTrace();
		}
		try {
			UIManager.setLookAndFeel(lookAndFeel);
		} catch (UnsupportedLookAndFeelException e) {
			System.err.println("Synth is not a supported look and feel");
			e.printStackTrace();
		}
	}

	private static class SpotlightLayerUI extends LayerUI<JPanel> {
		private static final long serialVersionUID = -2815331572730280489L;
		private boolean mActive;
		private int mX, mY;

		@Override
		public void installUI(JComponent c) {
			super.installUI(c);
			@SuppressWarnings("unchecked")
			JLayer<JPanel> jLayer = (JLayer<JPanel>) c;
			jLayer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK
					| AWTEvent.MOUSE_MOTION_EVENT_MASK);
		}

		@Override
		public void uninstallUI(JComponent c) {
			super.uninstallUI(c);
			@SuppressWarnings("unchecked")
			JLayer<JPanel> jLayer = (JLayer<JPanel>) c;
			jLayer.setLayerEventMask(0);
		}

		@Override
		public void paint(Graphics g, JComponent c) {
			super.paint(g, c);
			Graphics2D g2 = (Graphics2D) g.create();
			if (mActive) {
				/* Create a radial gradient, transparent in the middle */
				Point2D center = new 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 p = new RadialGradientPaint(center, radius,
						dist, colors);
				g2.setPaint(p);
				g2.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_OVER, .6f));
				g2.fillRect(0, 0, c.getWidth(), c.getHeight());
			}
			g2.dispose();
		}

		@Override
		protected void processMouseEvent(MouseEvent e,
				JLayer<? extends JPanel> l) {
			if (e.getID() == MouseEvent.MOUSE_ENTERED) {
				mActive = true;
			} else if (e.getID() == MouseEvent.MOUSE_EXITED) {
				mActive = false;
			}
			l.repaint();
		}

		@Override
		protected void processMouseMotionEvent(MouseEvent e,
				JLayer<? extends JPanel> l) {
			Point p = SwingUtilities.convertPoint(e.getComponent(),
					e.getPoint(), l);
			mX = p.x;
			mY = p.y;
			l.repaint();
		}
	}

	private static class WaitLayerUI extends LayerUI<JPanel> implements
			ActionListener {
		private static final long serialVersionUID = 3018547845595498783L;
		private boolean mIsRunning;
		private boolean mIsFadingOut;
		private Timer mTimer;
		private int mAngle;
		private int mFadeCount;
		private final int mFadeLimit = 15;

		@Override
		public void paint(Graphics g, JComponent c) {
			super.paint(g, c);// paint the view
			if (!mIsRunning) {
				return;
			}
			float fade = mFadeCount / mFadeLimit;
			Graphics2D g2 = (Graphics2D) g.create();
			/* Gray it out, in fact it uses the FOREGROUND of L&F */
			Composite urComposite = g2.getComposite();
			g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
					.5f * fade));
			int w = c.getWidth();
			int h = c.getHeight();
			g2.fillRect(0, 0, w, h);
			g2.setComposite(urComposite);
			/* Paint the wait indicator */
			int s = Math.min(w, h) / 5;
			int cx = w / 2;
			int cy = h / 2;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			g2.setStroke(new BasicStroke(s / 4, BasicStroke.CAP_ROUND,
					BasicStroke.JOIN_ROUND));
			g2.setPaint(Color.white);
			g2.rotate(Math.PI * mAngle / 180, cx, cy);
			for (int i = 0; i < 12; i++) {
				float scale = (11.0f - i) / 11.0f;
				g2.drawLine(cx + s, cy, cx + s * 2, cy);
				g2.rotate(-Math.PI / 6, cx, cy);
				g2.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_OVER, scale * fade));
			}
			g2.dispose();
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			if (mIsRunning) {
				firePropertyChange("tick", 0, 1);
				mAngle += 3;
				if (mAngle >= 360) {
					mAngle = 0;
				}
				if (mIsFadingOut) {
					if (--mFadeCount == 0) {
						mIsRunning = false;
						mTimer.stop();
					}
				} else if (mFadeCount < mFadeLimit) {
					mFadeCount++;
				}
			}
		}

		public void start() {
			if (mIsRunning) {
				return;
			}
			/* Run a thread for animation */
			mIsRunning = true;
			mIsFadingOut = false;
			mFadeCount = 0;
			int fps = 24;
			int tick = 1000 / fps;
			mTimer = new Timer(tick, this);
			mTimer.start();
		}

		public void stop() {
			mIsFadingOut = true;
		}

		@Override
		public void applyPropertyChange(PropertyChangeEvent pce,
				JLayer<? extends JPanel> l) {
			if ("tick".equals(pce.getPropertyName())) {
				l.repaint();
			}
		}
	}

	TestCase() {
		ButtonGroup entreeGroup = new ButtonGroup();
		JRadioButton radioButton = new JRadioButton("Beef", true);
		JRadioButton radioButton2 = new JRadioButton("Chicken");
		JRadioButton radioButton3 = new JRadioButton("Vegetable");
		entreeGroup.add(radioButton);
		entreeGroup.add(radioButton2);
		entreeGroup.add(radioButton3);
		JCheckBox jCheckBox = new JCheckBox("Ketchup");
		JCheckBox jCheckBox2 = new JCheckBox("Mustard");
		JCheckBox jCheckBox3 = new JCheckBox("Pickles");
		JLabel label = new JLabel("Special requests:");
		JTextField tf = new JTextField(15);
		final JLabel info = new JLabel();
		info.setName("customLabel");
		orderButton = new JButton("Place Order");
		orderButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				info.setText("default button clicked");
				if (stopper.isRunning())
					return;
				stopper.start();
				waitLayerUI.start();
				jLayer.setUI(waitLayerUI);
			}
		});
		JButton cancelButton = new JButton("Cancel");
		cancelButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				info.setText("cancel button clicked");
			}
		});
		add(radioButton);
		add(radioButton2);
		add(radioButton3);
		add(jCheckBox);
		add(jCheckBox2);
		add(jCheckBox3);
		add(label);
		add(tf);
		add(orderButton);
		add(cancelButton);
		add(info);
	}
}
星空123321 2014-01-05
  • 打赏
  • 举报
回复
看不懂啊继续加油啊
桃园闲人 2014-01-05
  • 打赏
  • 举报
回复
非常不错!抽时间看看。
欧亨利式结局 2014-01-05
  • 打赏
  • 举报
回复
很好啊
fearlessMore 2014-01-03
  • 打赏
  • 举报
回复
引用 28 楼 ruishenh 的回复:
只是一个小例子,为了说明问题而已。具体的美化因人而异,以及代码的拓展读者可以自己玩玩~
幸运小侯子 2014-01-03
  • 打赏
  • 举报
回复
fearlessMore 2014-01-02
  • 打赏
  • 举报
回复
谢谢raistlic在我学习jfc之初对我的帮助。。
fearlessMore 2014-01-02
  • 打赏
  • 举报
回复
引用 26 楼 Gaowen_HAN 的回复:
引用 25 楼 cl61917380 的回复:
这年头还有人做swing啊,好牛B。
只是有时开发的小应用需要图形界面的话,为什么不可以用呢呵呵
并且之前我听说Swing很丑很恐怖之类的,那就能美化下就美化下咯~
fearlessMore 2014-01-02
  • 打赏
  • 举报
回复
引用 25 楼 cl61917380 的回复:
这年头还有人做swing啊,好牛B。
只是有时开发的小应用需要图形界面的话,为什么不可以用呢呵呵
raistlic 2014-01-02
  • 打赏
  • 举报
回复
加载更多回复(20)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧