packagegradient;importjava.awt.Color;importjava.awt.Dimension;importjava.awt.Graphics;importjava.awt.Graphics2D;importjava.awt.Insets;importjava.awt.LinearGradientPaint;importjava.awt.MultipleGradientPaint;importjava.awt.Paint;importjava.awt.RadialGradientPaint;importjava.awt.RenderingHints;importjava.awt.event.KeyAdapter;importjava.awt.event.KeyEvent;importjava.awt.event.MouseAdapter;importjava.awt.event.MouseEvent;importjava.awt.event.MouseMotionAdapter;importjava.awt.geom.Ellipse2D;importjava.awt.geom.GeneralPath;importjava.awt.geom.Point2D;importjava.awt.geom.Rectangle2D;importjava.util.ArrayList;importjava.util.LinkedList;importjava.util.List;importjavax.swing.JFrame;importjavax.swing.JPanel;importjavax.swing.event.ChangeEvent;importjavax.swing.event.ChangeListener;/*使用方法:
渐变窗体:
a. 左键双击顶点的linear gradient 渐变区,改变渐变超出范围的重复绘制模式.
b. 左键双击fractions小按钮区,创建添加一个新的fraction按钮.
c. 左键双击fractions小按钮,弹出窗口选择窗口选择颜色.
d. 右键双击fractions小按钮,删除此fraction按钮.
e. 按住fractions小按钮可以拖动它,修改fractions的位置.
f. 左键双击辐射渐变区,改变辐射渐变的焦点(focus)到点击位置.
g. 在辐射渐变区按住左键拖动,改变辐射渐变的焦点.
h. 按下f,显示辐射渐变的圆周,为了方便看到更清楚的数据,默认这圆周是隐藏的.
i. 按下c,恢复辐射渐变的焦点到辐射渐变的圆心,焦点默认是与圆心重合.
颜色选择窗体:
a. 单击某一个颜色,则选中此颜色,并在底部的预览区显示出来.但颜色选择窗口不消失.
b. 双击某一个颜色,则选中此颜色,返回给调用者,颜色选择窗口消失.
c. 按下回车键,返回选中的颜色,颜色选择窗口消失.
d. 按下ESC键,返回传给颜色选择窗体的默认色,颜色选择窗口消失.
e. 下部的JSlider依次调节被选中颜色的red, green, blue, alpha,拖动并实时的在预览区显示出调整后颜色.
第三方程序集成使用方法: 在第三方程序中创建一个GradientGenerator对象,并添加到组件的某一部分,
并给此gradientGenerator添加上change listener:
gradientGenerator.addChangeListener(new ChangedListener() {
public void stateChanged(ChangeEvent e) {
float[] fractions = gradientGenerator.getFractons();
Color[] colors = gradientGenerator.getColors();
Point2D focus = gradientGenerator.calculateFocus(center, radius);
repaint(); // 使用这里得到的fractions, colors, focus等去绘制第三方程序中的渐变图形
});
这样,当gradient generator中的数据发生变化时,第三方程序里也会即时的反映出来.
1. 提示,现在Swing支持合建不规则窗体。
2. 此程序中,除了JSlider,其他的部分都是使用Java2D手动计算绘制出来的。
基于上面两点,可以自己创建一个统一的JSlider风格,
然后就可以把整个程序的外观风格做得在所有平台下都是一个样。*/
/*** *^o^*,本程序一惯还是一惯的作风,LGPL协议,什么版权的废话就不整了,希望修改得效果好的朋友给大家分享一下心得,在此权当扔出块板砖,
* 希望能砸出块暖玉来,嗷呜嗷呜嗷呜.*/@SuppressWarnings("serial")public class GradientGenerator extendsJPanel {private int width = 400; //整个Panel的宽度
private int height = 400; //整个Panel的高度
private Insets padding = new Insets(10, 10, 10, 10); //边距
private int thumbRectHeight = 20; //Fraction按钮区的高度
private int linearRectHeight = 40; //线性渐变区域的高度
private int radialRectHeight = 310; //辐射渐变区域的高度
private Ellipse2D radialCircle = new Ellipse2D.Float(); //辐射渐变的圆周
private Point2D focusPoint = new Point2D.Float(); //辐射渐变的焦点
private Point2D pressedPoint = new Point2D.Float(); //鼠标按下时的点
private Rectangle2D linearRect = new Rectangle2D.Float(); //线性渐变区域
private Rectangle2D thumbsRect = new Rectangle2D.Float(); //Fractions按钮区域
private Rectangle2D radialRect = new Rectangle2D.Float(); //辐射渐变区域
private Thumb selectedThumb = null; //被选中的Fraction按钮
private List thumbs = new ArrayList(); //Fractions按钮
private boolean showCircle = false; //显示辐射渐变的圆周
private List changeListeners = new LinkedList();private MultipleGradientPaint.CycleMethod cycleMethod =MultipleGradientPaint.CycleMethod.REFLECT;/*** 返回渐变的fractions数组
*
*@return
*/
public float[] getGradientFractions() {float[] fractions = new float[thumbs.size()];int i = 0;for(Thumb t : thumbs) {
fractions[i]= (float) ((t.getX() - padding.left) /linearRect.getWidth());++i;
}returnfractions;
}/*** 返回渐变的colors数组
*
*@return
*/
publicColor[] getGradientColors() {
Color[] colors= newColor[thumbs.size()];int i = 0;for(Thumb t : thumbs) {
colors[i]=t.getColor();++i;
}returncolors;
}/*** 利用指定圆的圆心和半径和当前的辐射渐变数据,计算相对于指定圆的焦点
*
*@paramcenter
* 圆心
*@paramradius
* 半径
*@return返回相对于指定圆的焦点*/
public Point2D calculateFocus(Point2D center, doubleradius) {
Point2D curCenter= newPoint2D.Double(radialCircle.getCenterX(), radialCircle.getCenterY());double curRadius = radialCircle.getWidth() / 2;double curFocusLen =GeometryUtil.distanceOfPoints(curCenter, focusPoint);double newFocusLen = radius * curFocusLen /curRadius;
Point2D newFocusPoint=GeometryUtil.extentPoint(curCenter, focusPoint, newFocusLen);//先移回原点,再移动到center的位置
newFocusPoint.setLocation(center.getX() -curCenter.getX(),
center.getY()-curCenter.getY());returnnewFocusPoint;
}publicGradientGenerator() {
setFocusable(true); //为了能接收键盘按键事件
afterResized();
resetThumbs(new float[] { 0.0f, 0.5f, 1.0f }, newColor[] { Color.BLACK, Color.BLUE,new Color(255, 255, 255, 220) });
handleEvents();
setBackground(Color.DARK_GRAY);
}//事件处理
private voidhandleEvents() {this.addMouseListener(newMouseAdapter() {
@Overridepublic voidmousePressed(MouseEvent e) {int x =e.getX();int y =e.getY();
pressedPoint.setLocation(x, y);//得到被选中的Thumb
for(Thumb t : thumbs) {if(t.contains(x, y)) {
t.setSelected(true);
selectedThumb=t;break;
}
}
repaint();
}
@Overridepublic voidmouseReleased(MouseEvent e) {for(Thumb t : thumbs) {
t.setSelected(false);
selectedThumb= null;
}
repaint();
}
@Overridepublic voidmouseClicked(MouseEvent e) {int x =e.getX();int y =e.getY();//左键双击
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {//如果在thumbs里面,则弹出颜色选择器
for(Thumb t : thumbs) {if(t.contains(x, y)) {
changeThumbColor(t);
repaint();return;
}
}//如果不在thumbs里,而在thumbs的区域里,则增加一个thumb
if(thumbsRect.contains(x, y)) {
insertThumbAt(x);
repaint();return;
}//修改focus的位置
if(radialRect.contains(x, y)) {
changeFocusPoint(newPoint2D.Float(x, y));
repaint();return;
}//在Linear rect里面,修改cycle method
if(linearRect.contains(x, y)) {
changeCycleMethod();
repaint();return;
}
}else if (e.getButton() == MouseEvent.BUTTON3 && e.getClickCount() == 2) {//右键双击
removeThumbAt(x, y);return;
}
}
});this.addMouseMotionListener(newMouseMotionAdapter() {
@Overridepublic voidmouseDragged(MouseEvent e) {//拖动滑块
if (selectedThumb != null) {int deltaX = e.getX() - (int) (selectedThumb.getX());int x = selectedThumb.getX() +deltaX;//不能超过边界
int maxRight = (int) (padding.left +linearRect.getWidth());if (x < padding.left || x > maxRight) { return; }int index =thumbs.indexOf(selectedThumb);int prevX =Integer.MIN_VALUE;int nextX =Integer.MAX_VALUE;//只能在前一个和后一个之间移动
if (index - 1 >= 0) {
prevX= (int) (thumbs.get(index - 1).getX());
}if (index + 1
nextX= (int) (thumbs.get(index + 1).getX());
}if (x > prevX && x
selectedThumb.setX(x);
repaint();
}return;
}else if(radialRect.contains(e.getX(), e.getY())) {int deltaX = (int) (e.getX() -pressedPoint.getX());int deltaY = (int) (e.getY() -pressedPoint.getY());
focusPoint.setLocation(focusPoint.getX()+ deltaX, focusPoint.getY() +deltaY);
pressedPoint.setLocation(e.getX(), e.getY());
repaint();
}
}
});this.addKeyListener(newKeyAdapter() {
@Overridepublic voidkeyReleased(KeyEvent e) {switch(e.getKeyCode()) {caseKeyEvent.VK_F:
showCircle= !showCircle;break;caseKeyEvent.VK_C:
changeFocusPoint(radialCircle.getCenterX(), radialCircle.getCenterY());break;
}
repaint();
}
});
}//执行监听器的事件
public voidfireChangeEvent() {for(ChangeListener l : changeListeners) {
l.stateChanged(new ChangeEvent(this));
}
}//改变超出渐变区的颜色渐变方式
public voidchangeCycleMethod() {
changeCycleMethod(cycleMethod);
}public voidchangeCycleMethod(MultipleGradientPaint.CycleMethod cycleMethod) {switch(cycleMethod) {caseNO_CYCLE:this.cycleMethod =MultipleGradientPaint.CycleMethod.REFLECT;break;caseREFLECT:this.cycleMethod =MultipleGradientPaint.CycleMethod.REPEAT;break;caseREPEAT:this.cycleMethod =MultipleGradientPaint.CycleMethod.NO_CYCLE;break;
}
}
@Overrideprotected voidpaintComponent(Graphics g) {super.paintComponent(g);
Graphics2D g2d=(Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawLinearRect(g2d);
drawThumbsRect(g2d);
drawRadialRect(g2d);
}//绘制fraction按钮所在区域
private voiddrawThumbsRect(Graphics2D g2d) {
g2d.setColor(new Color(255, 255, 255, 40));
g2d.fill(thumbsRect);//绘制fraction按钮
for(Thumb t : thumbs) {
t.paint(g2d);
}
}private voiddrawLinearRect(Graphics2D g2d) {//绘制线性渐变区域
float sx = (float) linearRect.getX();float sy = (float) linearRect.getY();float ex = (int) (sx +linearRect.getWidth());float ey =sy;float[] fractions =getGradientFractions();
Color[] colors=getGradientColors();
Paint p= newLinearGradientPaint(sx, sy, ex, ey, fractions, colors, cycleMethod);
TransparentPainter.paint(g2d, linearRect);
g2d.setPaint(p);
g2d.fill(linearRect);
}//绘制辐射渐变区
private voiddrawRadialRect(Graphics2D g2d) {float cx = (float) radialCircle.getCenterX();float cy = (float) radialCircle.getCenterY();float fx = (float) focusPoint.getX();float fy = (float) focusPoint.getY();float radius = (float) radialCircle.getWidth() / 2;float[] fractions =getGradientFractions();
Color[] colors=getGradientColors();
TransparentPainter.paint(g2d, radialRect);
Paint p= newRadialGradientPaint(cx, cy, radius, fx, fy, fractions, colors, cycleMethod);
g2d.setPaint(p);
g2d.fill(radialRect);if(showCircle) {//绘制辐射渐变的圆
g2d.setPaint(Color.BLACK);
g2d.draw(radialCircle);
}
}//最少需要两个渐变值,所以开始就创建两个fraction
public void resetThumbs(float[] fractions, Color[] colors) {if (fractions == null || colors == null) { throw newNullPointerException(); }if (fractions.length != colors.length) { throw newIllegalArgumentException("Fractions 和 Colors 参数个数不等"); }int x = (int) thumbsRect.getX();int w = (int) thumbsRect.getWidth();for (int i = 0; i < fractions.length; ++i) {
insertThumbAt(x+ (int) (w *fractions[i]), colors[i]);
}
}//在指定的水平位置插入Fraction按钮
private void insertThumbAt(intx) {
insertThumbAt(x, Color.BLUE);
}private void insertThumbAt(intx, Color color) {int index = 0;for(Thumb t : thumbs) {if (x >t.getX()) {
index++;
}
}int y = (int) (padding.top +linearRect.getHeight());
thumbs.add(index,newThumb(x, y, color));
fireChangeEvent();
}public void removeThumbAt(int x, inty) {for(Thumb t : thumbs) {if(t.contains(x, y)) {if (thumbs.size() > 2) {
thumbs.remove(t);
fireChangeEvent();break;
}
}
}
}private voidchangeThumbColor(Thumb thumb) {//弹出颜色选择器
Color newColor = ColorChooser.chooseColor(this, thumb.getColor());if (newColor != null) {
thumb.setColor(newColor);
fireChangeEvent();
}
}//改变焦点的位置
public void changeFocusPoint(double x, doubley) {
focusPoint.setLocation(x, y);
fireChangeEvent();
}private voidchangeFocusPoint(Point2D focusPoint) {
changeFocusPoint(focusPoint.getX(), focusPoint.getY());
}//当panel的大小改变时,再次调用此函数更新显示区域
private voidafterResized() {//
//padding-top//linear gradient area//thumbs area//padding = padding top//radial gradient area//padding-bottom// /线性渐变显示区域
int x =padding.left;int y =padding.top;int w = width - padding.left -padding.right;int h =linearRectHeight;
linearRect.setRect(x, y, w, h);//Fraction按钮所在区域
y +=linearRectHeight;
h=thumbRectHeight;
thumbsRect.setRect(x, y, w, h);//辐射渐变显示区域
y = padding.top + linearRectHeight + thumbRectHeight +padding.top;
h=radialRectHeight;
h=Math.min(w, h);
x= (width - w) / 2;
radialRect.setRect(x, y, w, h);//中心点和焦点
int cx = x + w / 2;int cy = y + h / 2;int radius = 100;
focusPoint.setLocation(cx, cy);
radialCircle.setFrame(cx- radius, cy - radius, radius + radius, radius +radius);
repaint();
}
@OverridepublicDimension getMinimumSize() {return newDimension(width, height);
}
@OverridepublicDimension getMaximumSize() {return newDimension(width, height);
}
@OverridepublicDimension getPreferredSize() {return newDimension(width, height);
}private static voidcreateGuiAndShow() {
JFrame frame= new JFrame("Gradient Generator");
JPanel panel= newJPanel();
panel.add(newGradientGenerator());
frame.setContentPane(newGradientGenerator());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();//使用此函数后always on top就不起作用了
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
}public static voidmain(String[] args) {
createGuiAndShow();
}
}classThumb {private intx;private inty;private int width = 16;private int height = 20;privateColor color;private booleanselected;privateGeneralPath outerPath;privateGeneralPath innerPath;public Thumb(int x, inty, Color color) {
setXY(x, y);this.color =color;
}public intgetX() {returnx;
}public void setX(intx) {
setXY(x, y);
}public intgetY() {returny;
}public void setY(inty) {
setXY(x, y);
}public intgetWidth() {returnwidth;
}public void setWidth(intwidth) {
setWidthHeight(width, height);
}public intgetHeight() {returnheight;
}public void setHeight(intheight) {
setWidthHeight(width, height);
}publicColor getColor() {returncolor;
}public voidsetColor(Color color) {this.color =color;
}public booleanisSelected() {returnselected;
}public void setSelected(booleanselected) {this.selected =selected;
}public boolean contains(int x, inty) {returnouterPath.contains(x, y);
}public void setXY(int x, inty) {this.x =x;this.y =y;
createPaths();
}public void setWidthHeight(int width, intheight) {this.width =width;this.height =height;
createPaths();
}private float[] fractions = new float[] { 0.0f, 0.5f, 1.0f};private Color[] colors = newColor[] { Color.ORANGE, Color.BLACK, Color.ORANGE.brighter() };public voidpaint(Graphics2D g2d) {//绘制大三角形按钮//Paint p = new GradientPaint(x, y, selected ? color.darker() : color,//x, y + height, Color.ORANGE);
Paint p = new LinearGradientPaint(x - width, y, x + width / 4, y, fractions, colors);
g2d.setPaint(p);
g2d.fill(outerPath);//绘制小三角形按钮
g2d.setColor(color);
g2d.fill(innerPath);
}//创建按钮的形状
private voidcreatePaths() {
outerPath= newGeneralPath();
outerPath.moveTo(x, y);
outerPath.lineTo(x+ width / 2, y +height);
outerPath.lineTo(x- width / 2, y +height);
outerPath.closePath();
innerPath= newGeneralPath();
innerPath.moveTo(x, y+ height / 2);
innerPath.lineTo(x+ width / 4, y +height);
innerPath.lineTo(x- width / 4, y +height);
innerPath.closePath();
}
}
[html] view plain copypackagegradient;importjava.awt.AWTEvent;importjava.awt.BorderLayout;importjava.awt.Color;importjava.awt.Component;importjava.awt.Dimension;importjava.awt.Graphics;importjava.awt.Graphics2D;importjava.awt.Insets;importjava.awt.RenderingHints;importjava.awt.Toolkit;importjava.awt.event.AWTEventListener;importjava.awt.event.KeyEvent;importjava.awt.event.MouseAdapter;importjava.awt.event.MouseEvent;importjava.awt.event.WindowAdapter;importjava.awt.event.WindowEvent;importjava.awt.geom.Rectangle2D;importjava.awt.image.BufferedImage;importjava.io.File;importjava.io.FileNotFoundException;importjava.util.ArrayList;importjava.util.List;importjava.util.Scanner;importjavax.swing.JComponent;importjavax.swing.JDialog;importjavax.swing.JPanel;importjavax.swing.JSlider;importjavax.swing.event.ChangeEvent;importjavax.swing.event.ChangeListener;/*** 创建一个模态的颜色选择对话框,可以加载用户预先定义存储好的颜色.
*
*@authorBiao
**/@SuppressWarnings("serial")public class ColorChooser extendsJDialog {private static ColorChooser instance = newColorChooser();private ColorPanel colorPanel = newColorPanel();privateColor color;public staticColor chooseColor(JComponent ower, Color defaultColor) {
instance.color=defaultColor;
instance.colorPanel.startSelect(defaultColor);
instance.pack();
instance.setLocationRelativeTo(ower);
instance.setVisible(true);returninstance.color;
}privateColorChooser() {
setTitle("Choose a color");
setModal(true);
setResizable(false);
setBackground(Color.DARK_GRAY);
getContentPane().add(colorPanel, BorderLayout.CENTER);this.addWindowListener(newWindowAdapter() {
@Overridepublic voidwindowClosing(WindowEvent e) {
gotoHell(color);
}
});
colorPanel.addChangeListener(newChangeListener() {
@Overridepublic voidstateChanged(ChangeEvent e) {
Color c=colorPanel.getColor();if(colorPanel.isDoubleClickSelection()) {
gotoHell(c);
}int r =c.getRed();int g =c.getGreen();int b =c.getBlue();int a =c.getAlpha();
String hex= ColorPanel.colorToHexString(newColor(r, g, b, a));
String title= String.format("RGBA(%d,%d,%d,%d) Hex(%s)", r, g, b, a, hex);
setTitle(title);
}
});//处理JDialog所有子组件的按键事件//按下回车使用选择的颜色,按下Esc返回默认传进来的颜色
Toolkit.getDefaultToolkit().addAWTEventListener(newAWTEventListener() {
@Overridepublic voideventDispatched(AWTEvent event) {
KeyEvent ke=(KeyEvent) event;if (ke.getID() ==KeyEvent.KEY_PRESSED) {if (event.getSource() instanceofComponent) {
Component com=(Component) event.getSource();if (ke.getKeyCode() == KeyEvent.VK_ESCAPE &&hasChild(com)) {
gotoHell(color);//取消时返回默认的颜色
} else if (ke.getKeyCode() == KeyEvent.VK_ENTER &&hasChild(com)) {
gotoHell(colorPanel.getColor());
}
}
}
}
}, AWTEvent.KEY_EVENT_MASK);
}//是否包含了组件
public booleanhasChild(Component c) {for (Component parent = c; parent != null; parent =parent.getParent()) {if (parent == this) { return true; }
}return false;
}//隐藏颜色选择对话框
public voidgotoHell(Color c) {
color= (c == null) ?color : c;
setVisible(false);
}
}
@SuppressWarnings("serial")class ColorPanel extendsJPanel {final static private int columnSize = 21; //每行最多显示21个颜色
final static private int sliderHeight = 20; //Slider的高度
final static private int previewHeight = 20; //预览区的高度
final static private int colorRectWidth = 20; //颜色小方块的宽度
final static private int colorRectHeight = 20;//颜色小方块的高度
private int width = 520; //Color panel的尺寸
private int height = 340;private Insets padding = new Insets(10, 10, 0, 10); //边距
private int margin =padding.top;private Color color =Color.WHITE;private List storedColors = new ArrayList(); //用户存储的颜色
private List defaultColors = new ArrayList(); //使用算法生成的默认颜色
private Rectangle2D previewRect = new Rectangle2D.Float(); //预览区域
private Rectangle2D colorsImageRect = new Rectangle2D.Double(); //显示颜色的区域
private BufferedImage colorsImage; //需要使用颜色信息来创建确定大小//调节rgba的slider
private JSlider redSlider = new JSlider(0, 255, 255);private JSlider greenSlider = new JSlider(0, 255, 255);private JSlider blueSlider = new JSlider(0, 255, 255);private JSlider alphaSlider = new JSlider(0, 255, 255);//双击时如果选中颜色,则选择完成
private boolean doubleClickSelection = false;private List changeListeners = new ArrayList();publicColorPanel() {//创建颜色和显示颜色的小方块缓冲图像
prepareColors();
prepareColorsImage();//窗口的大小需要用color buffer image的大小来确定,所以必须在这里调用
prepareSize();
preparePreview();
prepareSliders();this.addMouseListener(newMouseAdapter() {
@Overridepublic voidmouseClicked(MouseEvent e) {int x =e.getX();int y =e.getY();
Color c=getColorAt(x, y);if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) {//单击时设置选中的颜色
if (c != null) {
setColor(c);
fireStateChanged();
}
}else if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {//双击时返回选中的颜色,隐藏颜色选取窗口
if (c != null ||previewRect.contains(x, y)) {
setDoubleClickSelection(true);
fireStateChanged();
}
}
}
});
redSlider.addChangeListener(newChangeListener() {
@Overridepublic voidstateChanged(ChangeEvent e) {
setR(redSlider.getValue());
fireStateChanged();
}
});
greenSlider.addChangeListener(newChangeListener() {
@Overridepublic voidstateChanged(ChangeEvent e) {
setG(greenSlider.getValue());
fireStateChanged();
}
});
blueSlider.addChangeListener(newChangeListener() {
@Overridepublic voidstateChanged(ChangeEvent e) {
setB(blueSlider.getValue());
fireStateChanged();
}
});
alphaSlider.addChangeListener(newChangeListener() {
@Overridepublic voidstateChanged(ChangeEvent e) {
setA(alphaSlider.getValue());
fireStateChanged();
}
});
}
@Overrideprotected voidpaintComponent(Graphics g) {super.paintComponent(g);
setBackground(Color.DARK_GRAY);
Graphics2D g2d=(Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//绘制颜色方块的缓冲图片
int x = (int) colorsImageRect.getX();int y = (int) colorsImageRect.getY();int w = (int) colorsImageRect.getWidth();int h = (int) colorsImageRect.getHeight();
g2d.drawImage(colorsImage, x, y, w, h,null);//绘制颜色预览
TransparentPainter.paint(g2d, previewRect);
g2d.setPaint(color);
g2d.fill(previewRect);
}public voidstartSelect(Color color) {
setColor(color);
setDoubleClickSelection(false);
}public booleanisDoubleClickSelection() {returndoubleClickSelection;
}protected void setDoubleClickSelection(booleandoubleClickSelection) {this.doubleClickSelection =doubleClickSelection;
}//当属性改变事件发生时,调用监听器并且重绘
public voidfireStateChanged() {for(ChangeListener l : changeListeners) {
l.stateChanged(new ChangeEvent(this));
}
repaint();
}public voidaddChangeListener(ChangeListener l) {
changeListeners.add(l);
}public voidremoveChangeListener(ChangeListener l) {
changeListeners.remove(l);
}//选得鼠标选中的颜色
public Color getColorAt(int x, inty) {//如果不在显示颜色的图片中,则返回null
if (!colorsImageRect.contains(x, y)) { return null; }//以图片的左上角为原点
x -=colorsImageRect.getX();
y-=colorsImageRect.getY();if (y <=getHeightOfColorsRect(storedColors)) {int i = y / colorRectHeight * columnSize + x /colorRectWidth;return i >= storedColors.size() ? null: storedColors.get(i);
}else{
y-= getHeightOfColorsRect(storedColors) +margin;int i = y / colorRectHeight * columnSize + x /colorRectWidth;return i >= defaultColors.size() ? null: defaultColors.get(i);
}
}//返回当前选中的颜色
publicColor getColor() {returncolor;
}//设置当前颜色
public voidsetColor(Color color) {this.color = (color == null) ?Color.WHITE : color;
setSliderValues(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
}public void setColor(int r, int g, intb) {this.color = new Color(r, g, b, 255);
setSliderValues(r, g, b,255);
}public void setColor(int r, int g, int b, inta) {
r=clamp(r);
g=clamp(g);
b=clamp(b);
a=clamp(a);this.color = newColor(r, g, b, a);
setSliderValues(r, g, b, a);
}public void setR(intr) {
setColor(r, color.getGreen(), color.getBlue(), color.getAlpha());
}public void setG(intg) {
setColor(color.getRed(), g, color.getBlue(), color.getAlpha());
}public void setB(intb) {
setColor(color.getRed(), color.getGreen(), b, color.getAlpha());
}public void setA(inta) {
setColor(color.getRed(), color.getGreen(), color.getBlue(), a);
}public int clamp(intval) {
val= val < 0 ? 0: val;
val= val > 255 ? 255: val;returnval;
}//设置slier的值
private void setSliderValues(int r, int g, int b, inta) {
redSlider.setValue(r);
greenSlider.setValue(g);
blueSlider.setValue(b);
alphaSlider.setValue(a);
fireStateChanged();
}/*** 把16进制模式的字符串转化成颜色.
*
*@paramhex
* 表示颜色的16进制字符串,格式为#rgb, #rrggbb, #aarrggbb
*@return返回字符串的颜色,如果字符串格式不对,返回null*/
public staticColor parseColorHex(String hex) {//#rgb, #rrggbb, #aarrggbb//检查长度
if (hex == null || hex.length() != 4 && hex.length() != 7 && hex.length() != 9
&& hex.charAt(0) != '#') { return null; }//检查字符是否有效
for (int i = 1; i < hex.length(); ++i) {char aChar =hex.charAt(i);if (!('0' <= aChar && aChar <= '9') && !('a' <= aChar && aChar <= 'f')&& !('A' <= aChar && aChar <= 'F')) { return null; }
}if (hex.length() == 4) {//#rgb
int r = Integer.valueOf(hex.charAt(1) + "" + hex.charAt(1), 16);int g = Integer.valueOf(hex.charAt(2) + "" + hex.charAt(2), 16);int b = Integer.valueOf(hex.charAt(3) + "" + hex.charAt(3), 16);return newColor(r, g, b);
}else if (hex.length() == 7) {//#rrggbb
int r = Integer.valueOf(hex.substring(1, 3), 16);int g = Integer.valueOf(hex.substring(3, 5), 16);int b = Integer.valueOf(hex.substring(5, 7), 16);return newColor(r, g, b);
}else if (hex.length() == 9) {//#aarrggbb
int a = Integer.valueOf(hex.substring(1, 3), 16);int r = Integer.valueOf(hex.substring(3, 5), 16);int g = Integer.valueOf(hex.substring(5, 7), 16);int b = Integer.valueOf(hex.substring(7, 9), 16);return newColor(r, g, b, a);
}return null;
}public static char[] hexDight = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B','C', 'D', 'E', 'F'};/*** 把颜色的表示转换为16进制表示#rrggbbaa
*
*@paramcolor
*@return返回颜色的16进制字符串*/
public staticString colorToHexString(Color color) {if (color == null) { return "null"; }int r =color.getRed();int g =color.getGreen();int b =color.getBlue();int a =color.getAlpha();
StringBuilder sb= new StringBuilder("#");
sb.append(hexDight[a>> 4 & 0xF]);
sb.append(hexDight[a& 0xF]);
sb.append(hexDight[r>> 4 & 0xF]);
sb.append(hexDight[r& 0xF]);
sb.append(hexDight[g>> 4 & 0xF]);
sb.append(hexDight[g& 0xF]);
sb.append(hexDight[b>> 4 & 0xF]);
sb.append(hexDight[b& 0xF]);returnsb.toString();
}private voidprepareColors() {//从文件中读取颜色
try{
Scanner scanner= new Scanner(new File("resources/colors.txt"));while(scanner.hasNextLine()) {try{
Color c=parseColorHex(scanner.nextLine().trim());if (c != null) {
storedColors.add(c);
}
}catch(Exception e) {
}
}
}catch(FileNotFoundException e) {
e.printStackTrace();
}//创建一些默认的颜色
final float delta = 0.2f;for (float r = 0; r <= 1.0; r +=delta) {for (float g = 0; g <= 1.0; g +=delta) {for (float b = 0; b <= 1.0; b +=delta) {
defaultColors.add(newColor(r, g, b));
}
}
}
}private int getHeightOfColorsRect(Listli) {int row = (int) Math.ceil(li.size() / (float) columnSize);return row *colorRectWidth;
}private voidprepareColorsImage() {
margin=padding.top;int w = columnSize *colorRectWidth;int h = getHeightOfColorsRect(storedColors) + getHeightOfColorsRect(defaultColors) +margin;int x = 0;int y = 0;
colorsImageRect.setRect(padding.top, padding.top, w, h);
colorsImage= newBufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d=colorsImage.createGraphics();//绘制用户存储的颜色
for (int i = 0; i < storedColors.size(); ++i) {
g2d.setPaint(storedColors.get(i));
g2d.fillRect(x, y, colorRectWidth, colorRectHeight);
x+=colorRectWidth;if ((i + 1) % columnSize == 0) {
x= 0;
y+=colorRectHeight;
}
}
x= 0;
y= getHeightOfColorsRect(storedColors) +margin;//绘制默认的颜色
for (int i = 0; i < defaultColors.size(); ++i) {
g2d.setPaint(defaultColors.get(i));
g2d.fillRect(x, y, colorRectWidth, colorRectHeight);
x+=colorRectWidth;if ((i + 1) % columnSize == 0) {
x= 0;
y+=colorRectHeight;
}
}
}private voidprepareSize() {
width= padding.left + colorsImage.getWidth() +padding.right;
height= padding.top + colorsImage.getHeight() + padding.top + previewHeight +sliderHeight;
}private voidpreparePreview() {int x =padding.left;int y = height - sliderHeight -previewHeight;int w = width - padding.left -padding.right;
previewRect.setRect(x, y, w, previewHeight);
}private voidprepareSliders() {
setLayout(null);int margin = 0; //slider之间的间隔,实际没必须
int h =sliderHeight;int w = (width - padding.left - padding.right) / 4;int x =padding.left;int y = height - h + 2;
redSlider.setBounds(x, y, w, h);
x+= w +margin;
greenSlider.setBounds(x, y, w, h);
x+= w +margin;
blueSlider.setBounds(x, y, w, h);
x+= w +margin;
alphaSlider.setBounds(x, y, w, h);
add(redSlider);
add(greenSlider);
add(blueSlider);
add(alphaSlider);
}
@OverridepublicDimension getMinimumSize() {return newDimension(width, height);
}
@OverridepublicDimension getMaximumSize() {return newDimension(width, height);
}
@OverridepublicDimension getPreferredSize() {return newDimension(width, height);
}
}
[html] view plain copypackagegradient;importjava.awt.Color;importjava.awt.Graphics2D;importjava.awt.geom.Rectangle2D;/*** 绘制Photoshop中透明色的效果.
*
*@authorBiao
**/
public classTransparentPainter {public static voidpaint(Graphics2D g2d, Rectangle2D rect) {
g2d.setClip(rect);int sx = (int) rect.getX();int sy = (int) rect.getY();int w = (int) rect.getWidth();int h = (int) rect.getHeight();
Color color=Color.WHITE;
Color color1=Color.WHITE;
Color color2=Color.LIGHT_GRAY;int delta = 10;boolean odd = false;for (int y = sy; y <= h + sy; y +=delta) {
color= (odd) ?color1 : color2;for (int x = sx; x <= w + sx; x +=delta) {
g2d.setPaint(color);
g2d.fillRect(x, y, w, h);
color= (color == color1) ?color2 : color1;
}
odd= !odd;
}
g2d.setClip(null);
}
}
[html] view plain copypackagegradient;importjava.awt.geom.Point2D;public classGeometryUtil {//两点之间的距离
public static doubledistanceOfPoints(Point2D p1, Point2D p2) {double disX = p2.getX() -p1.getX();double disY = p2.getY() -p1.getY();double dis = Math.sqrt(disX * disX + disY *disY);returndis;
}//两点的中点
public staticPoint2D middlePoint(Point2D p1, Point2D p2) {double x = (p1.getX() + p2.getX()) / 2;double y = (p1.getY() + p2.getY()) / 2;return newPoint2D.Double(x, y);
}//在两点所在直线上,以从startPoint到endPoint为方向,离startPoint的距离disToStartPoint的点
public static Point2D extentPoint(Point2D startPoint, Point2D endPoint, doubledisToStartPoint) {double disX = endPoint.getX() -startPoint.getX();double disY = endPoint.getY() -startPoint.getY();double dis = Math.sqrt(disX * disX + disY *disY);double sin = (endPoint.getY() - startPoint.getY()) /dis;double cos = (endPoint.getX() - startPoint.getX()) /dis;double deltaX = disToStartPoint *cos;double deltaY = disToStartPoint *sin;return new Point2D.Double(startPoint.getX() + deltaX, startPoint.getY() +deltaY);
}
}