Swing按钮控件(JButton)重绘

2014-11-29 13:51:31|?次阅读|上传:wustguangh【已有?条评论】发表评论

关键词:Java, Swing, 界面设计|来源:唯设编程网

进行界面设计的时候,有时需要设计一些特殊的按钮,如音乐播放器的原型,三角形按钮。如果Swing提供的默认按钮无法满足我们要求,我们就需要对按钮控件(JButton)进行重绘。

Swing按钮重绘的基本原理是:创建一个继承自JButton的扩展按钮类,在其中重载paintComponent方法,这个方法用来实现控件的显示界面绘制。为了使我们的按钮可以响应鼠标移入、移出按钮等事件,我们还对它添加了鼠标监听器,这通过addMouseListener方法实现。

本例子我们实现的扩展按钮效果如下:

Swing扩展按钮

下面是扩展按钮类ExtJButton的实现方法:

package Test;
/**
 */


import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Arc2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;

/**
 * Custom ExtJButton
 * 
 * @version 0.1.0
 */
public class ExtJButton extends JButton {
	private static final long serialVersionUID = 39082560987930759L;
	public static final Color BUTTON_COLOR1 = new Color(205, 255, 205);
	public static final Color BUTTON_COLOR2 = new Color(51, 154, 47);
	public static final Color BUTTON_FOREGROUND_COLOR = Color.WHITE;
	private boolean hover;
	private int style;
	public static final int ROUND_RECT = 0;
	public static final int LEFT_ROUND_RECT = 1;
	public static final int RIGHT_ROUND_RECT = 2;
	public static final int BALL = 3;
	public static final int STAR = 4;

	public ExtJButton() {
		this(ROUND_RECT);
	}

	public ExtJButton(int style) {
		this.style = style;
		if (BALL == style) {
			setPreferredSize(new Dimension(42, 42));
		} else if (STAR == style) {
			setPreferredSize(new Dimension(42, 42));
		}
		setFont(new Font("system", Font.PLAIN, 12));
		setBorderPainted(false);
		setForeground(BUTTON_COLOR2);
		setFocusPainted(false);
		setContentAreaFilled(false);
		addMouseListener(new MouseAdapter() {
			@Override
			public void mouseEntered(MouseEvent e) {
				setForeground(BUTTON_FOREGROUND_COLOR);
				hover = true;
				repaint();
			}

			@Override
			public void mouseExited(MouseEvent e) {
				setForeground(BUTTON_COLOR2);
				hover = false;
				repaint();
			}
		});
	}

	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D g2d = (Graphics2D) g.create();
		int h = getHeight();
		int w = getWidth();
		float tran = 1F;
		if (!hover) {
			tran = 0.3F;
		}

		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		GradientPaint p1;
		GradientPaint p2;
		if (getModel().isPressed()) {
			p1 = new GradientPaint(0, 0, new Color(0, 0, 0), 0, h - 1,
					new Color(100, 100, 100));
			p2 = new GradientPaint(0, 1, new Color(0, 0, 0, 50), 0, h - 3,
					new Color(255, 255, 255, 100));
		} else {
			p1 = new GradientPaint(0, 0, new Color(100, 100, 100), 0, h - 1,
					new Color(0, 0, 0));
			p2 = new GradientPaint(0, 1, new Color(255, 255, 255, 100), 0,
					h - 3, new Color(0, 0, 0, 50));
		}
		g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
				tran));
		GradientPaint gp = new GradientPaint(0.0F, 0.0F, BUTTON_COLOR1, 0.0F,
				h, BUTTON_COLOR2, true);
		g2d.setPaint(gp);
		switch (style) {
		case ROUND_RECT: {
			RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0,
					w - 1, h - 1, 20, 20);
			Shape clip = g2d.getClip();
			g2d.clip(r2d);
			g2d.fillRect(0, 0, w, h);
			g2d.setClip(clip);
			g2d.setPaint(p1);
			g2d.drawRoundRect(0, 0, w - 1, h - 1, 20, 20);
			g2d.setPaint(p2);
			g2d.drawRoundRect(1, 1, w - 3, h - 3, 18, 18);
			break;
		}
		case LEFT_ROUND_RECT: {
			RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0,
					(w - 1) + 20, h - 1, 20, 20);
			Shape clip = g2d.getClip();
			g2d.clip(r2d);
			g2d.fillRect(0, 0, w, h);
			g2d.setClip(clip);
			g2d.setPaint(p1);
			g2d.drawRoundRect(0, 0, (w - 1) + 20, h - 1, 20, 20);
			g2d.setPaint(p2);
			g2d.drawRoundRect(1, 1, (w - 3) + 20, h - 3, 18, 18);
			g2d.setPaint(p1);
			g2d.drawLine(w - 1, 1, w - 1, h);
			g2d.setPaint(p2);
			g2d.drawLine(w - 2, 2, w - 2, h - 1);
			break;
		}
		case RIGHT_ROUND_RECT: {
			RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(-20, 0,
					(w - 1) + 20, h - 1, 20, 20);
			Shape clip = g2d.getClip();
			g2d.clip(r2d);
			g2d.fillRect(0, 0, w, h);
			g2d.setClip(clip);
			g2d.setPaint(p1);
			g2d.drawRoundRect(-20, 0, (w - 1) + 20, h - 1, 20, 20);
			g2d.setPaint(p2);
			g2d.drawRoundRect(-19, 1, (w - 3) + 20, h - 3, 18, 18);
			g2d.setPaint(p1);
			g2d.drawLine(0, 1, 0, h);
			g2d.setPaint(p2);
			g2d.drawLine(1, 2, 1, h - 1);
			break;
		}
		case BALL: {
			Arc2D.Float a2d = new Arc2D.Float(0, 0, w, h, 0, 360, Arc2D.CHORD);
			Shape clip = g2d.getClip();
			g2d.clip(a2d);
			g2d.fillRect(0, 0, w, h);
			g2d.setClip(clip);
			g2d.setPaint(p1);
			g2d.drawOval(0, 0, w - 1, h - 1);
			g2d.setPaint(p2);
			g2d.drawOval(1, 1, w - 3, h - 3);
			break;
		}
		case STAR: {
			int x = w / 2;
			int y = h / 2;
			int r = w / 2;
			// 计算五个顶点
			Point[] ps = new Point[5];
			for (int i = 0; i <= 4; i++) {
				ps[i] = new Point((int) (x - r
						* Math.sin((i * 72 + 36) * 2 * Math.PI / 360)),
						(int) (y + r
								* Math.cos((i * 72 + 36) * 2 * Math.PI / 360)));
			}
			GeneralPath star = new GeneralPath();
			star.moveTo(ps[3].x, ps[3].y);
			star.lineTo(ps[0].x, ps[0].y);
			star.lineTo(ps[2].x, ps[2].y);
			star.lineTo(ps[4].x, ps[4].y);
			star.lineTo(ps[1].x, ps[1].y);
			star.lineTo(ps[3].x, ps[3].y);
			star.closePath();
			Shape clip = g2d.getClip();
			g2d.clip(star);
			g2d.fillRect(0, 0, w, h);
			g2d.setClip(clip);
			g2d.setPaint(p1);
			g2d.draw(star);
			g2d.setPaint(p2);
			g2d.draw(star);
			break;
		}
		default:
			break;
		}
		g2d.dispose();
		super.paintComponent(g);
	}
}

用于测试的窗口类如下:

package Test;
import java.awt.FlowLayout;

import javax.swing.JFrame;

public class TestButtonFrame extends JFrame {
	ExtJButton rountBtn = null;
	ExtJButton starBtn = null;
	ExtJButton ballBtn = null;
	
	public TestButtonFrame() {
		super("测试");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setSize(300, 200);
		this.getContentPane().setLayout(new FlowLayout());

		rountBtn = new ExtJButton();
		rountBtn.setText("登录");		
		this.getContentPane().add(rountBtn);
		
		starBtn = new ExtJButton(ExtJButton.STAR);
		starBtn.setText("*");		
		this.getContentPane().add(starBtn);
		
		ballBtn = new ExtJButton(ExtJButton.BALL);
		ballBtn.setText("||");		
		this.getContentPane().add(ballBtn);
		
		this.setVisible(true);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new TestButtonFrame();
	}

}

如果需要重载其它Swing控件,基本的思路和实现方法与重载JButton类似,可以参考该例子的基本流程和思路。

发表评论0条 】
网友评论(共?条评论)..
Swing按钮控件(JButton)重绘