Java 重新绘制JButton

使用paintComponent()方法绘制的各种Button:

正常状态:

Java 重新绘制JButton_第1张图片

获得焦点状态:

Java 重新绘制JButton_第2张图片

被按下状态:

Java 重新绘制JButton_第3张图片

被释放状态:

Java 重新绘制JButton_第4张图片

实现代码:

package com.han;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.LineMetrics;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

@SuppressWarnings("serial")
public class JButton_Bg extends JFrame {

	public JButton_Bg() {
		for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			if (laf.getName().equals("Nimbus")) {
				try {
					UIManager.setLookAndFeel(laf.getClassName());
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		// TODO Auto-generated constructor stub
		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		final JButton button = new MyButton("button 2");

		c.add(button);
		JButton button2 = new JButton("button 2");
		c.add(button2);
		button2.setBackground(Color.blue);

		JButton button3 = new MyButton2("Cancel");
		c.add(button3);

		// 完全重绘的Button,其Text的HTML设置特性消失
		// JButton button4 = new
		// MyButton3("<html><font size=12>Sub</font></html>");
		JButton button4 = new MyButton3("Sub");
		// button4.setFont(new Font("Serif", Font.PLAIN, 14));
		c.add(button4);
	}

	private class MyButton extends JButton {
		private String text;
		private String state = "normal";
		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		Shape shape;

		// 无参构造继承时自动调用,而有参构造继承时则需手动重写
		MyButton(String text) {
			// super("<html><font size=5>" + text + "</font></html>");
			super(text);
			this.text = text;

			// 下 面的代码块若是放到下面的paintComponent()方法里则Swing界面初始化时,
			// 布局管理器还是采用的是系统默认的PreferredSize。因为构造函数要优先于
			// paintComponent()方法执行。
			Dimension preferredSize = getPreferredSize();
			Dimension preferredSizeNew = new Dimension(preferredSize.width,
					preferredSize.width);
			setPreferredSize(preferredSizeNew);
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			int width = this.getPreferredSize().width;
			int height = this.getPreferredSize().height;

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				shape = new Ellipse2D.Double(width / 2 - height / 2, 0, height,
						height);
				g2.fill(shape);
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));

			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2, 0, height,
						height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				// draw background pattern
				int offsetCenter = 1;
				Point2D center = new Point2D.Float(width / 2 + offsetCenter,
						height / 2 + offsetCenter);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2
						+ offsetCenter, offsetCenter, height, height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2)
								+ offsetCenter,
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent()))
								+ offsetCenter);
			} else if (state.equals("released")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2, 0, height,
						height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					repaint();
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
					repaint();
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被按下,");
					state = "pressed";
					repaint();
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被释放,");
					state = "released";
					repaint();
				}

			});

		}

		// Gives the UI delegate an opportunity to define the precise shape of
		// this component for the sake of mouse processing.
		@Override
		public boolean contains(int x, int y) {
			if (shape.contains(x, y)) {
				return true;
			} else {
				return false;
			}
		}
	}

	private class MyButton2 extends JButton {
		private String text;
		private String state = "normal";
		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";
		
		Shape shape;

		// Initialize the size of the button according to the length and width
		// of the text string
		MyButton2(String text) {
			super(text);
			this.text = text;
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			int width = this.getWidth();
			int height = this.getHeight();

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(0, 0, 0, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				shape = new RoundRectangle2D.Double(0, 0, width, height,
						height, height);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("released")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					repaint();
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
					repaint();
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被按下,");
					state = "pressed";
					repaint();
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被释放,");
					state = "released";
					repaint();
				}

			});

		}
		
		@Override
		public boolean contains(int x, int y) {
			if (shape.contains(x, y)) {
				return true;
			} else {
				return false;
			}
		}
	}

	private class MyButton3 extends JButton {
		private String text;
		private String state = "normal";

		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		Shape shape;
		
		// Initialize the size of the button according to the length and width
		// of the text string
		MyButton3(String text) {
			super(text);
			this.text = text;
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			int width = this.getWidth();
			int height = this.getHeight();

			if (state.equals("normal")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(0, 0, 0, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				shape = new RoundRectangle2D.Double(0, 0, width, height,
						height, height);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				g2.setColor(new Color(0, 147, 255));
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				double borderWidth = 2.0f; // 2 pixels
				g2.fill(new RoundRectangle2D.Double(borderWidth, borderWidth,
						width - borderWidth * 2.0f,
						height - borderWidth * 2.0f, height - borderWidth
								* 2.0f, height - borderWidth * 2.0f));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("released")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					repaint();
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
					repaint();
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被按下,");
					state = "pressed";
					repaint();
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被释放,");
					state = "released";
					repaint();
				}

			});

		}
		
		@Override
		public boolean contains(int x, int y) {
			if (shape.contains(x, y)) {
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JButton_Bg frame = new JButton_Bg();
		frame.pack();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

}


添加了背景图片的Button:

Java 重新绘制JButton_第5张图片

显然当按钮大小改变时,背景图片有失真。

实现代码:

package com.han;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.LineMetrics;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

@SuppressWarnings("serial")
public class JButton_Bg extends JFrame {

	public JButton_Bg() {
		for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			if (laf.getName().equals("Nimbus")) {
				try {
					UIManager.setLookAndFeel(laf.getClassName());
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		// TODO Auto-generated constructor stub
		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		final JButton button = new MyButton("button 2");

		c.add(button);
		JButton button2 = new JButton("button 2");
		c.add(button2);
		button2.setBackground(Color.blue);

		JButton button3 = new MyButton2("Cancel");
		c.add(button3);

		// 完全重绘的Button,其Text的HTML设置特性消失
		// JButton button4 = new
		// MyButton3("<html><font size=12>Sub</font></html>");
		JButton button4 = new MyButton3("Sub");
		// button4.setFont(new Font("Serif", Font.PLAIN, 14));
		c.add(button4);
	}

	private class MyButton extends JButton {
		private String text;
		private String state = "normal";
		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		Shape shape;

		// 无参构造继承时自动调用,而有参构造继承时则需手动重写
		MyButton(String text) {
			// super("<html><font size=5>" + text + "</font></html>");
			super(text);
			this.text = text;

			// 下 面的代码块若是放到下面的paintComponent()方法里则Swing界面初始化时,
			// 布局管理器还是采用的是系统默认的PreferredSize。因为构造函数要优先于
			// paintComponent()方法执行。
			Dimension preferredSize = getPreferredSize();
			Dimension preferredSizeNew = new Dimension(preferredSize.width,
					preferredSize.width);
			setPreferredSize(preferredSizeNew);
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			int width = this.getPreferredSize().width;
			int height = this.getPreferredSize().height;

			 BufferedImage img;
			 try {
			 img = ImageIO.read(this.getClass().getResource(
			 "/images/icon.jpg"));
			 g2.drawImage(img, 0, 0, width, height, this);
			 } catch (IOException e1) {
			 // TODO Auto-generated catch block
			 e1.printStackTrace();
			 }

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				shape = new Ellipse2D.Double(width / 2 - height / 2, 0, height,
						height);
				g2.fill(shape);
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));

			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2, 0, height,
						height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				// draw background pattern
				int offsetCenter = 1;
				Point2D center = new Point2D.Float(width / 2 + offsetCenter,
						height / 2 + offsetCenter);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2
						+ offsetCenter, offsetCenter, height, height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2)
								+ offsetCenter,
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent()))
								+ offsetCenter);
			} else if (state.equals("released")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2, 0, height,
						height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					repaint();
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
					repaint();
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被按下,");
					state = "pressed";
					repaint();
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被释放,");
					state = "released";
					repaint();
				}

			});

		}

		// Gives the UI delegate an opportunity to define the precise shape of
		// this component for the sake of mouse processing.
		@Override
		public boolean contains(int x, int y) {
			if (shape.contains(x, y)) {
				return true;
			} else {
				return false;
			}
		}
	}

	private class MyButton2 extends JButton {
		private String text;
		private String state = "normal";
		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";
		
		Shape shape;

		// Initialize the size of the button according to the length and width
		// of the text string
		MyButton2(String text) {
			super(text);
			this.text = text;
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			int width = this.getWidth();
			int height = this.getHeight();

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(0, 0, 0, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				shape = new RoundRectangle2D.Double(0, 0, width, height,
						height, height);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("released")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					repaint();
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
					repaint();
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被按下,");
					state = "pressed";
					repaint();
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被释放,");
					state = "released";
					repaint();
				}

			});

		}
		
		@Override
		public boolean contains(int x, int y) {
			if (shape.contains(x, y)) {
				return true;
			} else {
				return false;
			}
		}
	}

	private class MyButton3 extends JButton {
		private String text;
		private String state = "normal";

		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		Shape shape;
		
		// Initialize the size of the button according to the length and width
		// of the text string
		MyButton3(String text) {
			super(text);
			this.text = text;
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			int width = this.getWidth();
			int height = this.getHeight();

			if (state.equals("normal")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(0, 0, 0, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				shape = new RoundRectangle2D.Double(0, 0, width, height,
						height, height);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				g2.setColor(new Color(0, 147, 255));
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				double borderWidth = 2.0f; // 2 pixels
				g2.fill(new RoundRectangle2D.Double(borderWidth, borderWidth,
						width - borderWidth * 2.0f,
						height - borderWidth * 2.0f, height - borderWidth
								* 2.0f, height - borderWidth * 2.0f));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("released")) {
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new RoundRectangle2D.Double(0, 0, width, height,
						height, height));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					repaint();
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
					repaint();
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被按下,");
					state = "pressed";
					repaint();
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.print("鼠标按键被释放,");
					state = "released";
					repaint();
				}

			});

		}
		
		@Override
		public boolean contains(int x, int y) {
			if (shape.contains(x, y)) {
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JButton_Bg frame = new JButton_Bg();
		frame.pack();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

}


其中的核心修改代码:

Java 重新绘制JButton_第6张图片


使用基于Nimbus包的Customize出属于自己的Look and Feel:

使用Painter可以保留按钮的HTML特性(因为自己不需要重画 Text)


package com.han;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Painter;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;

/**
 * 使用了Nimbus的个性化组件方法。使用Painter可以保留按钮的HTML特性(因为自己不需要重画 Text)。
 * 
 * @see JButton_Bg
 * @author HAN
 * 
 */
@SuppressWarnings("serial")
public class JButton_Bg_2 extends JFrame {
	static JButton button;
	static JButton buttonBg;
	static JButton buttonExtended1;
	static JButton buttonExtended2;
	static JButton buttonExtended3;

	public JButton_Bg_2() {
		for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			if (laf.getName().equals("Nimbus")) {
				try {
					UIManager.setLookAndFeel(laf.getClassName());
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		button = new JButton("button");
		c.add(button);

		buttonBg = new JButton("button");
		c.add(buttonBg);
		buttonBg.setBackground(Color.blue);

		buttonExtended1 = new JButtonExtended1("OK");
		buttonExtended1.setForeground(Color.GREEN);
		c.add(buttonExtended1);

		buttonExtended2 = new JButtonExtended2("<html><u>C</u>ancel</html>");
		c.add(buttonExtended2);

		buttonExtended3 = new JButtonExtended3("Sub");
		c.add(buttonExtended3);
	}

	private class JButtonExtended1 extends JButton {
		Shape shape;

		JButtonExtended1(String text) {
			super(text);

			// 设置按钮默认文本颜色为红色
			this.setForeground(Color.RED);

			// 设置按钮默认区域为正方形
			Dimension preferredSize = getPreferredSize();
			Dimension preferredSizeNew = new Dimension(preferredSize.width,
					preferredSize.width);
			setPreferredSize(preferredSizeNew);

			/* customize button */
			UIDefaults sliderDefaults = new UIDefaults();
			sliderDefaults.put("Button.contentMargins",
					new Insets(6, 14, 6, 14));
			sliderDefaults.put("Button[Enabled].backgroundPainter",
					new Painter<JComponent>() {
						public void paint(Graphics2D g, JComponent c,
								int width, int height) {
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = height / 2;
							float[] dist = { 0.0f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							shape = new Ellipse2D.Double(
									width / 2 - height / 2, 0, height, height);
							g.fill(shape);
						}
					});
			sliderDefaults.put("Button[MouseOver].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = height / 2;
							float[] dist = { 0.2f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new Ellipse2D.Double(width / 2 - height / 2,
									0, height, height));
						}

					});
			sliderDefaults.put("Button[Focused].backgroundPainter",
					new Painter<JComponent>() {
						// The paint is the same as MouseOver
						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = height / 2;
							float[] dist = { 0.2f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new Ellipse2D.Double(width / 2 - height / 2,
									0, height, height));
						}

					});
			sliderDefaults.put("Button[Focused+Pressed].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							int offsetCenter = 1;
							Point2D center = new Point2D.Float(width / 2
									+ offsetCenter, height / 2 + offsetCenter);
							float radius = height / 2;
							float[] dist = { 0.2f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new Ellipse2D.Double(width / 2 - height / 2
									+ offsetCenter, offsetCenter, height,
									height));
						}

					});
			this.putClientProperty("Nimbus.Overrides", sliderDefaults);
			// replace the defaults
			this.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
		}

		@Override
		public boolean contains(int x, int y) {
			try {
				if (shape.contains(x, y)) {
					return true;
				} else {
					return false;
				}
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
			return super.contains(x, y);
		}
	}

	private class JButtonExtended2 extends JButton {
		Shape shape;

		JButtonExtended2(String text) {
			super(text);
			/* customize button */
			UIDefaults sliderDefaults = new UIDefaults();
			// sliderDefaults.put("Button.defaultButtonFollowsFocus", false);
			sliderDefaults.put("Button.contentMargins",
					new Insets(6, 14, 6, 14));
			sliderDefaults.put("Button[Enabled].backgroundPainter",
					new Painter<JComponent>() {
						public void paint(Graphics2D g, JComponent c,
								int width, int height) {
							// // Rendering operations have no effect outside of
							// // the clipping area.
							// g.setClip(0, 0, height, height);
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(0, 0, 0, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							shape = new RoundRectangle2D.Double(0, 0, width,
									height, height, height);
							g.fill(shape);

						}
					});
			sliderDefaults.put("Button[MouseOver].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused].backgroundPainter",
					new Painter<JComponent>() {
						// The paint is the same as MouseOver
						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused+Pressed].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 1.0f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			this.putClientProperty("Nimbus.Overrides", sliderDefaults);
			// replace the defaults
			this.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
		}

		@Override
		public boolean contains(int x, int y) {
			try {
				if (shape.contains(x, y)) {
					return true;
				} else {
					return false;
				}
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
			return super.contains(x, y);
		}
	}

	private class JButtonExtended3 extends JButton {
		Shape shape;

		JButtonExtended3(String text) {
			super(text);
			/* customize button */
			UIDefaults sliderDefaults = new UIDefaults();
			sliderDefaults.put("Button.contentMargins",
					new Insets(6, 14, 6, 14));
			sliderDefaults.put("Button[Enabled].backgroundPainter",
					new Painter<JComponent>() {
						public void paint(Graphics2D g, JComponent c,
								int width, int height) {
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(0, 0, 0, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							shape = new RoundRectangle2D.Double(0, 0, width,
									height, height, height);
							g.fill(shape);
						}
					});
			sliderDefaults.put("Button[MouseOver].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused].backgroundPainter",
					new Painter<JComponent>() {
						// The paint is the same as MouseOver
						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused+Pressed].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							g.setColor(new Color(0, 147, 255));
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 1.0f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							double borderWidth = 0.0f; // 0 pixels, no border
							g.fill(new RoundRectangle2D.Double(borderWidth,
									borderWidth, width - borderWidth * 2.0f,
									height - borderWidth * 2.0f, height
											- borderWidth * 2.0f, height
											- borderWidth * 2.0f));
						}

					});
			this.putClientProperty("Nimbus.Overrides", sliderDefaults);
			// replace the defaults
			this.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
		}

		@Override
		public boolean contains(int x, int y) {
			try {
				if (shape.contains(x, y)) {
					return true;
				} else {
					return false;
				}
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
			return super.contains(x, y);
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JButton_Bg_2 frame = new JButton_Bg_2();
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// If you want to ensure that a particular component gains the focus
		// the first time a window is activated, you can call the
		// requestFocusInWindow method on the component after the component
		// has been realized, but before the frame is displayed.
		frame.pack(); // Realize the components.
		// This button will have the initial focus.
		buttonExtended2.requestFocusInWindow();
		frame.setVisible(true);// Display the window.
	}
}

下面的只是对以上总共3种方法做了代码优化:

package com.han;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.LineMetrics;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * 使用了重绘JButton的个性化组件方法。使用paint()不可以保留按钮的HTML特性(因为目前自己
 * 还没找到怎么画带HTML特性的String的方法)。
 * <p>
 * 采用了fire JButton的ActionEvent方法来画各种不同的按钮状态。
 * 
 * @see JButton_Bg_2
 * @see JButton_Bg_3
 * @author HAN
 * 
 */
@SuppressWarnings("serial")
public class JButton_Bg extends JFrame {

	public JButton_Bg() {
		for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			if (laf.getName().equals("Nimbus")) {
				try {
					UIManager.setLookAndFeel(laf.getClassName());
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		// TODO Auto-generated constructor stub
		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		final JButton button = new MyButton("button 2");

		c.add(button);
		JButton button2 = new JButton("button 2");
		c.add(button2);
		button2.setBackground(Color.blue);

		JButton button3 = new MyButton2("Cancel");
		c.add(button3);

		// 完全重绘的Button,其Text的HTML设置特性消失
		// JButton button4 = new
		// MyButton3("<html><font size=12>Sub</font></html>");
		JButton button4 = new MyButton3("Sub");
		// button4.setFont(new Font("Serif", Font.PLAIN, 14));
		c.add(button4);
	}

	private class MyButton extends JButton {
		private String text;
		private String state = "normal";
		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		private int width;
		private int height;
		private Shape shape;

		// 无参构造继承时自动调用,而有参构造继承时则需手动重写
		MyButton(String text) {
			// super("<html><font size=5>" + text + "</font></html>");
			super(text);
			this.text = text;

			// 下面的代码块若是放到下面的paintComponent()方法里则Swing界面初始化时,
			// 布局管理器还是采用的是系统默认的PreferredSize。因为构造函数要优先于
			// paintComponent()方法执行。
			Dimension preferredSize = getPreferredSize();
			Dimension preferredSizeNew = new Dimension(preferredSize.width,
					preferredSize.width);
			setPreferredSize(preferredSizeNew);

			// 自定义鼠标热点区域shape
			width = getPreferredSize().width;
			height = getPreferredSize().height;
			shape = new Ellipse2D.Double(width / 2 - height / 2, 0, height,
					height);
		}

		@Override
		protected void paintComponent(Graphics g) {
			System.out.println("paintComponent");
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				// draw background pattern
				int offsetCenter = 1;
				Point2D center = new Point2D.Float(width / 2 + offsetCenter,
						height / 2 + offsetCenter);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(new Ellipse2D.Double(width / 2 - height / 2
						+ offsetCenter, offsetCenter, height, height));
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2)
								+ offsetCenter,
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent()))
								+ offsetCenter);
			} else if (state.equals("released")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = height / 2;
				float[] dist = { 0.2f, 1.0f };
				Color[] colors = { new Color(0, 0, 0, 255),
						new Color(255, 255, 255, 0) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				g2.setColor(Color.RED);
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
					// repaint();// 可有可无,因为鼠标事件本身自动触发paintComponent()
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("鼠标按键被按下,");
					state = "pressed";
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("鼠标按键被释放,");
					state = "released";
				}

			});

		}

		// Gives the UI delegate an opportunity to define the precise shape of
		// this component for the sake of mouse processing.
		@Override
		public boolean contains(int x, int y) {
			return shape.contains(x, y);
		}
	}

	private class MyButton2 extends JButton {
		private String text;
		private String state = "normal";
		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		private int width;
		private int height;
		private Shape shape;

		MyButton2(String text) {
			super(text);
			this.text = text;

			// 自定义鼠标热点区域shape
			this.width = getPreferredSize().width;
			this.height = getPreferredSize().height;
			this.shape = new RoundRectangle2D.Double(0, 0, width, height,
					height, height);
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(0, 0, 0, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("released")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("鼠标按键被按下,");
					state = "pressed";
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("鼠标按键被释放,");
					state = "released";
				}

			});

		}

		@Override
		public boolean contains(int x, int y) {
			return shape.contains(x, y);
		}
	}

	private class MyButton3 extends JButton {
		private String text;
		private String state = "normal";

		// private String state = "focused";
		// private String state = "pressed";
		// private String state = "released";

		private int width;
		private int height;
		private Shape shape;

		MyButton3(String text) {
			super(text);
			this.text = text;

			// 自定义鼠标热点区域shape
			this.width = getPreferredSize().width;
			this.height = getPreferredSize().height;
			this.shape = new RoundRectangle2D.Double(0, 0, width, height,
					height, height);
		}

		@Override
		protected void paintComponent(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			if (state.equals("normal")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(0, 0, 0, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("focused")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("pressed")) {
				// draw background pattern
				g2.setColor(new Color(0, 147, 255));
				g2.fill(shape);
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 1.0f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				double borderWidth = 2.0f; // 2 pixels
				g2.fill(new RoundRectangle2D.Double(borderWidth, borderWidth,
						width - borderWidth * 2.0f,
						height - borderWidth * 2.0f, height - borderWidth
								* 2.0f, height - borderWidth * 2.0f));
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			} else if (state.equals("released")) {
				// draw background pattern
				Point2D center = new Point2D.Float(width / 2, height / 2);
				float radius = width / 2;
				float[] dist = { 0.0f, 0.8f };
				Color[] colors = { new Color(255, 255, 255, 0),
						new Color(20, 20, 20, 255) };
				RadialGradientPaint paint = new RadialGradientPaint(center,
						radius, dist, colors);
				g2.setPaint(paint);
				g2.fill(shape);
				// draw string text
				Font defaultFont = getFont();
				g2.setFont(defaultFont);
				g2.setColor(Color.BLACK);
				Rectangle2D rect = defaultFont.getStringBounds(text,
						g2.getFontRenderContext());
				LineMetrics lineMetrics = defaultFont.getLineMetrics(text,
						g2.getFontRenderContext());
				g2.drawString(
						text,
						(float) (width / 2 - rect.getWidth() / 2),
						(float) ((height / 2) + ((lineMetrics.getAscent() + lineMetrics
								.getDescent()) / 2 - lineMetrics.getDescent())));
			}

			addMouseListener(new MouseAdapter() {

				@Override
				public void mouseEntered(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移入组件");
					state = "focused";
				}

				@Override
				public void mouseExited(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("光标移出组件");
					state = "normal";
				}

				@Override
				public void mousePressed(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("鼠标按键被按下,");
					state = "pressed";
				}

				@Override
				public void mouseReleased(MouseEvent e) {
					// TODO Auto-generated method stub
					System.out.println("鼠标按键被释放,");
					state = "released";
				}

			});

		}

		@Override
		public boolean contains(int x, int y) {
			return shape.contains(x, y);
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JButton_Bg frame = new JButton_Bg();
		frame.pack();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

}

package com.han;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * 使用了重绘JButton的个性化组件方法。使用paint()保留了按钮的HTML特性(因为通过 setContentAreafilled(false) +
 * super.paintComponent(g) 这一方法使我们不需画带HTML特性的String)。
 * <p>
 * 采用了JButton的getModel()方法(State model for buttons.)来画各种不同的按钮状态。
 * 
 * @see JButton_Bg
 * @see JButton_Bg_3
 * @author HAN
 * 
 */
@SuppressWarnings("serial")
public class JButton_Bg_2 extends JFrame {

	public JButton_Bg_2() {
		for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			if (laf.getName().equals("Nimbus")) {
				try {
					UIManager.setLookAndFeel(laf.getClassName());
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		// TODO Auto-generated constructor stub
		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		final JButton button = new MyButton("button 2");
		System.out.println(button.isPreferredSizeSet());
		c.add(button);
		JButton button2 = new JButton("button 2");
		c.add(button2);
		button2.setBackground(Color.blue);
		System.out.println(button2.isPreferredSizeSet());
		JButton button3 = new MyButton2("Cancel");
		c.add(button3);

		// 完全重绘的Button,其Text的HTML设置特性消失
		// JButton button4 = new
		// MyButton3("<html><font size=12>Sub</font></html>");
		JButton button4 = new MyButton3("<html>Su<u>b</u></html>");
		// button4.setFont(new Font("Serif", Font.PLAIN, 14));
		c.add(button4);
	}

	private class MyButton extends JButton {
		private int width;
		private int height;
		private Shape shape;

		// 无参构造继承时自动调用,而有参构造继承时则需手动重写
		MyButton(String text) {
			super(text);
			setContentAreaFilled(false);
			setForeground(Color.RED);

			// 下面的代码块若是放到下面的paintComponent()方法里则Swing界面初始化时,
			// 布局管理器还是采用的是系统默认的PreferredSize。因为构造函数要优先于
			// paintComponent()方法执行。
			// 变方形按钮为圆形
			Dimension preferredSize = getPreferredSize();
			Dimension preferredSizeNew = new Dimension(preferredSize.width,
					preferredSize.width);
			setPreferredSize(preferredSizeNew);

			// 自定义鼠标热点区域shape
			width = getPreferredSize().width;
			height = getPreferredSize().height;
			shape = new Ellipse2D.Double(width / 2 - height / 2, 0, height,
					height);
		}

		@Override
		protected void paintComponent(Graphics g) {
			System.out.println();
			System.out.print("paintComponent\t");
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			if (this.getModel().isEnabled()) {
				System.out.print("isEnabled\t");
				if (this.getModel().isRollover()) {
					System.out.print("isRollover\t");
					if (this.getModel().isPressed()) {
						System.out.print("isPressed\t");
						// draw background pattern
						int offsetCenter = 1;
						Point2D center = new Point2D.Float(width / 2
								+ offsetCenter, height / 2 + offsetCenter);
						float radius = height / 2;
						float[] dist = { 0.2f, 1.0f };
						Color[] colors = { new Color(0, 0, 0, 255),
								new Color(255, 255, 255, 0) };
						RadialGradientPaint paint = new RadialGradientPaint(
								center, radius, dist, colors);
						g2.setPaint(paint);
						g2.fill(new Ellipse2D.Double(width / 2 - height / 2
								+ offsetCenter, offsetCenter, height, height));
					} else {
						// draw background pattern
						Point2D center = new Point2D.Float(width / 2,
								height / 2);
						float radius = height / 2;
						float[] dist = { 0.2f, 1.0f };
						Color[] colors = { new Color(0, 0, 0, 255),
								new Color(255, 255, 255, 0) };
						RadialGradientPaint paint = new RadialGradientPaint(
								center, radius, dist, colors);
						g2.setPaint(paint);
						g2.fill(shape);
					}

				} else {
					System.out.print("Normal\t");
					// draw background pattern
					Point2D center = new Point2D.Float(width / 2, height / 2);
					float radius = height / 2;
					float[] dist = { 0.0f, 1.0f };
					Color[] colors = { new Color(0, 0, 0, 255),
							new Color(255, 255, 255, 0) };
					RadialGradientPaint paint = new RadialGradientPaint(center,
							radius, dist, colors);
					g2.setPaint(paint);
					g2.fill(shape);
				}
			}
			super.paintComponent(g);
		}

		// Gives the UI delegate an opportunity to define the precise shape of
		// this component for the sake of mouse processing.
		@Override
		public boolean contains(int x, int y) {
			return shape.contains(x, y);
		}
	}

	private class MyButton2 extends JButton {
		private int width;
		private int height;
		private Shape shape;

		MyButton2(String text) {
			super(text);
			setContentAreaFilled(false);

			// 自定义鼠标热点区域shape
			this.width = getPreferredSize().width;
			this.height = getPreferredSize().height;
			this.shape = new RoundRectangle2D.Double(0, 0, width, height,
					height, height);
		}

		protected void paintComponent(Graphics g) {
			System.out.println();
			System.out.print("paintComponent\t");
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			if (this.getModel().isEnabled()) {
				System.out.print("isEnabled\t");
				if (this.getModel().isRollover()) {
					System.out.print("isRollover\t");
					if (this.getModel().isPressed()) {
						System.out.print("isPressed\t");
						// draw background pattern
						Point2D center = new Point2D.Float(width / 2,
								height / 2);
						float radius = width / 2;
						float[] dist = { 0.0f, 1.0f };
						Color[] colors = { new Color(255, 255, 255, 0),
								new Color(20, 20, 20, 255) };
						RadialGradientPaint paint = new RadialGradientPaint(
								center, radius, dist, colors);
						g2.setPaint(paint);
						g2.fill(shape);
					} else {
						// draw background pattern
						Point2D center = new Point2D.Float(width / 2,
								height / 2);
						float radius = width / 2;
						float[] dist = { 0.0f, 0.8f };
						Color[] colors = { new Color(255, 255, 255, 0),
								new Color(20, 20, 20, 255) };
						RadialGradientPaint paint = new RadialGradientPaint(
								center, radius, dist, colors);
						g2.setPaint(paint);
						g2.fill(shape);
					}

				} else {
					System.out.print("Normal\t");
					// draw background pattern
					Point2D center = new Point2D.Float(width / 2, height / 2);
					float radius = width / 2;
					float[] dist = { 0.0f, 0.8f };
					Color[] colors = { new Color(255, 255, 255, 0),
							new Color(0, 0, 0, 255) };
					RadialGradientPaint paint = new RadialGradientPaint(center,
							radius, dist, colors);
					g2.setPaint(paint);
					g2.fill(shape);
				}
			}
			super.paintComponent(g);
		}

		@Override
		public boolean contains(int x, int y) {
			return shape.contains(x, y);
		}
	}

	private class MyButton3 extends JButton {
		private int width;
		private int height;
		private Shape shape;

		MyButton3(String text) {
			super(text);
			setContentAreaFilled(false);

			// 自定义鼠标热点区域shape
			this.width = getPreferredSize().width;
			this.height = getPreferredSize().height;
			this.shape = new RoundRectangle2D.Double(0, 0, width, height,
					height, height);
		}

		protected void paintComponent(Graphics g) {
			System.out.println();
			System.out.print("paintComponent\t");
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);

			if (this.getModel().isEnabled()) {
				System.out.print("isEnabled\t");
				if (this.getModel().isRollover()) {
					System.out.print("isRollover\t");
					if (this.getModel().isPressed()) {
						System.out.print("isPressed\t");
						// draw background pattern
						g2.setColor(new Color(0, 147, 255));
						g2.fill(new RoundRectangle2D.Double(0, 0, width,
								height, height, height));
						Point2D center = new Point2D.Float(width / 2,
								height / 2);
						float radius = width / 2;
						float[] dist = { 0.0f, 1.0f };
						Color[] colors = { new Color(255, 255, 255, 0),
								new Color(20, 20, 20, 255) };
						RadialGradientPaint paint = new RadialGradientPaint(
								center, radius, dist, colors);
						g2.setPaint(paint);
						double borderWidth = 2.0f; // 2 pixels
						g2.fill(new RoundRectangle2D.Double(borderWidth,
								borderWidth, width - borderWidth * 2.0f, height
										- borderWidth * 2.0f, height
										- borderWidth * 2.0f, height
										- borderWidth * 2.0f));
					} else {
						// draw background pattern
						Point2D center = new Point2D.Float(width / 2,
								height / 2);
						float radius = width / 2;
						float[] dist = { 0.0f, 0.8f };
						Color[] colors = { new Color(255, 255, 255, 0),
								new Color(20, 20, 20, 255) };
						RadialGradientPaint paint = new RadialGradientPaint(
								center, radius, dist, colors);
						g2.setPaint(paint);
						g2.fill(shape);
					}

				} else {
					System.out.print("Normal\t");
					// draw background pattern
					Point2D center = new Point2D.Float(width / 2, height / 2);
					float radius = width / 2;
					float[] dist = { 0.0f, 0.8f };
					Color[] colors = { new Color(255, 255, 255, 0),
							new Color(0, 0, 0, 255) };
					RadialGradientPaint paint = new RadialGradientPaint(center,
							radius, dist, colors);
					g2.setPaint(paint);
					g2.fill(shape);
				}
			}
			super.paintComponent(g);
		}

		@Override
		public boolean contains(int x, int y) {
			return shape.contains(x, y);
		}

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JButton_Bg_2 frame = new JButton_Bg_2();
		frame.pack();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}

}

package com.han;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Painter;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;

/**
 * 使用了Nimbus的个性化组件方法。使用Painter可以保留按钮的HTML特性(因为自己不需要重画 Text)。
 * 
 * @see JButton_Bg
 * @see JButton_Bg_2
 * @author HAN
 * 
 */
@SuppressWarnings("serial")
public class JButton_Bg_3 extends JFrame {
	static JButton button;
	static JButton buttonBg;
	static JButton buttonExtended1;
	static JButton buttonExtended2;
	static JButton buttonExtended3;

	public JButton_Bg_3() {
		for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
			if (laf.getName().equals("Nimbus")) {
				try {
					UIManager.setLookAndFeel(laf.getClassName());
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		button = new JButton("button");
		c.add(button);

		buttonBg = new JButton("button");
		c.add(buttonBg);
		buttonBg.setBackground(Color.blue);

		buttonExtended1 = new JButtonExtended1("OK");
		buttonExtended1.setForeground(Color.GREEN);
		c.add(buttonExtended1);

		buttonExtended2 = new JButtonExtended2("<html><u>C</u>ancel</html>");
		c.add(buttonExtended2);

		buttonExtended3 = new JButtonExtended3("Sub");
		c.add(buttonExtended3);
	}

	private class JButtonExtended1 extends JButton {
		private Shape shape;

		JButtonExtended1(String text) {
			super(text);

			// 设置按钮默认文本颜色为红色
			this.setForeground(Color.RED);

			// 设置按钮默认区域为正方形
			Dimension preferredSize = getPreferredSize();
			Dimension preferredSizeNew = new Dimension(preferredSize.width,
					preferredSize.width);
			setPreferredSize(preferredSizeNew);

			/* customize button */
			UIDefaults sliderDefaults = new UIDefaults();
			sliderDefaults.put("Button.contentMargins",
					new Insets(6, 14, 6, 14));
			sliderDefaults.put("Button[Enabled].backgroundPainter",
					new Painter<JComponent>() {
						public void paint(Graphics2D g, JComponent c,
								int width, int height) {
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = height / 2;
							float[] dist = { 0.0f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							shape = new Ellipse2D.Double(
									width / 2 - height / 2, 0, height, height);
							g.fill(shape);
						}
					});
			sliderDefaults.put("Button[MouseOver].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = height / 2;
							float[] dist = { 0.2f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new Ellipse2D.Double(width / 2 - height / 2,
									0, height, height));
						}

					});
			sliderDefaults.put("Button[Focused].backgroundPainter",
					new Painter<JComponent>() {
						// The paint is the same as MouseOver
						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = height / 2;
							float[] dist = { 0.2f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new Ellipse2D.Double(width / 2 - height / 2,
									0, height, height));
						}

					});
			sliderDefaults.put("Button[Focused+Pressed].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							int offsetCenter = 1;
							Point2D center = new Point2D.Float(width / 2
									+ offsetCenter, height / 2 + offsetCenter);
							float radius = height / 2;
							float[] dist = { 0.2f, 1.0f };
							Color[] colors = { new Color(0, 0, 0, 255),
									new Color(255, 255, 255, 0) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new Ellipse2D.Double(width / 2 - height / 2
									+ offsetCenter, offsetCenter, height,
									height));
						}

					});
			this.putClientProperty("Nimbus.Overrides", sliderDefaults);
			// replace the defaults
			this.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
		}

		@Override
		public boolean contains(int x, int y) {
			try {
				if (shape.contains(x, y)) {
					return true;
				} else {
					return false;
				}
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
			return super.contains(x, y);
		}
	}

	private class JButtonExtended2 extends JButton {
		Shape shape;

		JButtonExtended2(String text) {
			super(text);
			/* customize button */
			UIDefaults sliderDefaults = new UIDefaults();
			// sliderDefaults.put("Button.defaultButtonFollowsFocus", false);
			sliderDefaults.put("Button.contentMargins",
					new Insets(6, 14, 6, 14));
			sliderDefaults.put("Button[Enabled].backgroundPainter",
					new Painter<JComponent>() {
						public void paint(Graphics2D g, JComponent c,
								int width, int height) {
							// // Rendering operations have no effect outside of
							// // the clipping area.
							// g.setClip(0, 0, height, height);
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(0, 0, 0, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							shape = new RoundRectangle2D.Double(0, 0, width,
									height, height, height);
							g.fill(shape);

						}
					});
			sliderDefaults.put("Button[MouseOver].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused].backgroundPainter",
					new Painter<JComponent>() {
						// The paint is the same as MouseOver
						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused+Pressed].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 1.0f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			this.putClientProperty("Nimbus.Overrides", sliderDefaults);
			// replace the defaults
			this.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
		}

		@Override
		public boolean contains(int x, int y) {
			try {
				if (shape.contains(x, y)) {
					return true;
				} else {
					return false;
				}
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
			return super.contains(x, y);
		}
	}

	private class JButtonExtended3 extends JButton {
		Shape shape;

		JButtonExtended3(String text) {
			super(text);
			/* customize button */
			UIDefaults sliderDefaults = new UIDefaults();
			sliderDefaults.put("Button.contentMargins",
					new Insets(6, 14, 6, 14));
			sliderDefaults.put("Button[Enabled].backgroundPainter",
					new Painter<JComponent>() {
						public void paint(Graphics2D g, JComponent c,
								int width, int height) {
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(0, 0, 0, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							shape = new RoundRectangle2D.Double(0, 0, width,
									height, height, height);
							g.fill(shape);
						}
					});
			sliderDefaults.put("Button[MouseOver].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused].backgroundPainter",
					new Painter<JComponent>() {
						// The paint is the same as MouseOver
						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 0.8f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
						}

					});
			sliderDefaults.put("Button[Focused+Pressed].backgroundPainter",
					new Painter<JComponent>() {

						@Override
						public void paint(Graphics2D g, JComponent object,
								int width, int height) {
							// TODO Auto-generated method stub
							g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
									RenderingHints.VALUE_ANTIALIAS_ON);
							// draw background pattern
							g.setColor(new Color(0, 147, 255));
							g.fill(new RoundRectangle2D.Double(0, 0, width,
									height, height, height));
							Point2D center = new Point2D.Float(width / 2,
									height / 2);
							float radius = width / 2;
							float[] dist = { 0.0f, 1.0f };
							Color[] colors = { new Color(255, 255, 255, 0),
									new Color(20, 20, 20, 255) };
							RadialGradientPaint paint = new RadialGradientPaint(
									center, radius, dist, colors);
							g.setPaint(paint);
							double borderWidth = 0.0f; // 0 pixels, no border
							g.fill(new RoundRectangle2D.Double(borderWidth,
									borderWidth, width - borderWidth * 2.0f,
									height - borderWidth * 2.0f, height
											- borderWidth * 2.0f, height
											- borderWidth * 2.0f));
						}

					});
			this.putClientProperty("Nimbus.Overrides", sliderDefaults);
			// replace the defaults
			this.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
		}

		@Override
		public boolean contains(int x, int y) {
			try {
				if (shape.contains(x, y)) {
					return true;
				} else {
					return false;
				}
			} catch (NullPointerException e) {
				System.out.println("NullPointerException");
			}
			return super.contains(x, y);
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		JButton_Bg_3 frame = new JButton_Bg_3();
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// If you want to ensure that a particular component gains the focus
		// the first time a window is activated, you can call the
		// requestFocusInWindow method on the component after the component
		// has been realized, but before the frame is displayed.
		frame.pack(); // Realize the components.
		// This button will have the initial focus.
		buttonExtended2.requestFocusInWindow();
		frame.setVisible(true);// Display the window.
	}
}


你可能感兴趣的:(Java 重新绘制JButton)